diff --git a/docs/architecture/11-patterns.md b/docs/architecture/11-patterns.md new file mode 100644 index 0000000..0d37d1d --- /dev/null +++ b/docs/architecture/11-patterns.md @@ -0,0 +1,96 @@ +--- +sidebar_position: 11 +--- + +# Паттерны проектирования + +Паттерн проектирования — это часто встречающееся решение определённой проблемы при проектировании архитектуры программ. + +В отличие от готовых функций или библиотек, паттерн нельзя просто взять и скопировать в программу. Паттерн представляет собой не какой-то конкретный код, а общую концепцию решения той или иной проблемы, которую нужно будет ещё подстроить под нужды вашей программы. + +Паттерны часто путают с алгоритмами, ведь оба понятия описывают типовые решения каких-то известных проблем. Но если алгоритм — это чёткий набор действий, то паттерн — это высокоуровневое описание решения, реализация которого может отличаться в двух разных программах. + +Если привести аналогии, то алгоритм — это кулинарный рецепт с чёткими шагами, а паттерн — инженерный чертёж, на котором нарисовано решение, но не конкретные шаги его реализации. + +## Из чего состоит паттерн? +Описания паттернов обычно очень формальны и чаще всего состоят из таких пунктов: + +- проблема, которую решает паттерн; +- мотивации к решению проблемы способом, который предлагает паттерн; +- структуры классов, составляющих решение; +- примера на одном из языков программирования; +- особенностей реализации в различных контекстах; +- связей с другими паттернами. + +Такой формализм в описании позволил создать обширный каталог паттернов, проверив каждый из них на состоятельность. + +## Классификация паттернов +Паттерны отличаются по уровню сложности, детализации и охвата проектируемой системы. Проводя аналогию со строительством, вы можете повысить безопасность перекрёстка, поставив светофор, а можете заменить перекрёсток целой автомобильной развязкой с подземными переходами. + +Самые низкоуровневые и простые паттерны — _идиомы_. Они не универсальны, поскольку применимы только в рамках одного языка программирования. + +Самые универсальные — _архитектурные паттерны_, которые можно реализовать практически на любом языке. Они нужны для проектирования всей программы, а не отдельных её элементов. + +Кроме того, паттерны отличаются и предназначением. В этой книге будут рассмотрены три основные группы паттернов: + +- **[Порождающие паттерны](https://refactoring.guru/ru/design-patterns/creational-patterns)** беспокоятся о гибком создании объектов без внесения в программу лишних зависимостей. +- **[Структурные паттерны](https://refactoring.guru/ru/design-patterns/structural-patterns)** показывают различные способы построения связей между объектами. +- **[Поведенческие паттерны](https://refactoring.guru/ru/design-patterns/behavioral-patterns)** заботятся об эффективной коммуникации между объектами. + + +## Зачем знать паттерны? +Вы можете вполне успешно работать, не зная ни одного паттерна. Более того, вы могли уже не раз реализовать какой-то из паттернов, даже не подозревая об этом. + +Но осознанное владение инструментом как раз и отличает профессионала от любителя. Вы можете забить гвоздь молотком, а можете и дрелью, если сильно постараетесь. Но профессионал знает, что главная фишка дрели совсем не в этом. Итак, зачем же знать паттерны? + +- **Проверенные решения.** Вы тратите меньше времени, используя готовые решения, вместо повторного изобретения велосипеда. До некоторых решений вы смогли бы додуматься и сами, но многие могут быть для вас открытием. + +- **Стандартизация кода.** Вы делаете меньше просчётов при проектировании, используя типовые унифицированные решения, так как все скрытые проблемы в них уже давно найдены. + +- **Общий программистский словарь.** Вы произносите название паттерна, вместо того, чтобы час объяснять другим программистам, какой крутой дизайн вы придумали и какие классы для этого нужны. + +## Критика паттернов +Паттерны были описаны более 20-ти лет назад, поэтому только ленивый не успел бросить в них камень. Давайте рассмотрим самую популярную критику. + +### Костыли для слабого языка программирования +Нужда в паттернах появляется тогда, когда люди выбирают для своего проекта язык программирования с недостаточным уровнем абстракции. В этом случае, паттерны — это костыль, который придаёт этому языку суперспособности. + +Например, паттерн **Стратегия** в современных языках можно реализовать простой анонимной (лямбда) функцией. + +### Неэффективные решения +Паттерны пытаются стандартизировать подходы, которые и так уже широко используются. Эта стандартизация кажется некоторым людям догмой и они реализуют паттерны «как в книжке», не приспосабливая паттерны к реалиям проекта. + +### Неоправданное применение +Если у тебя в руках молоток, то все предметы вокруг начинают напоминать гвозди. + +Похожая проблема возникает у новичков, которые только-только познакомились с паттернами. Вникнув в паттерны, человек пытается применить свои знания везде. Даже там, где можно было бы обойтись кодом попроще. + +## Каталог паттернов проектирования +- **[Порождающие:](https://refactoring.guru/ru/design-patterns/creational-patterns)** Отвечают за удобное и безопасное создание новых объектов или даже целых семейств объектов. + - [Фабричный метод](https://refactoring.guru/ru/design-patterns/factory-method) + - [Абстрактная фабрика](https://refactoring.guru/ru/design-patterns/abstract-factory) + - [Строитель](https://refactoring.guru/ru/design-patterns/builder) + - [Прототип](https://refactoring.guru/ru/design-patterns/prototype) + - [Одиночка](https://refactoring.guru/ru/design-patterns/singleton) +- **[Структурные:](https://refactoring.guru/ru/design-patterns/structural-patterns)** Отвечают за построение удобных в поддержке иерархий классов. + - [Адаптер](https://refactoring.guru/ru/design-patterns/adapter) + - [Мост](https://refactoring.guru/ru/design-patterns/bridge) + - [Компоновщик](https://refactoring.guru/ru/design-patterns/composite) + - [Декоратор](https://refactoring.guru/ru/design-patterns/decorator) + - [Фасад](https://refactoring.guru/ru/design-patterns/facade) + - [Легковес](https://refactoring.guru/ru/design-patterns/flyweight) + - [Заместитель](https://refactoring.guru/ru/design-patterns/proxy) +- **[Поведенческие:](https://refactoring.guru/ru/design-patterns/behavioral-patterns)** Решают задачи эффективного и безопасного взаимодействия между объектами программы. + - [Цепочка обязанностей](https://refactoring.guru/ru/design-patterns/chain-of-responsibility) + - [Команда](https://refactoring.guru/ru/design-patterns/command) + - [Итератор](https://refactoring.guru/ru/design-patterns/iterator) + - [Посредник](https://refactoring.guru/ru/design-patterns/mediator) + - [Снимок](https://refactoring.guru/ru/design-patterns/memento) + - [Наблюдатель](https://refactoring.guru/ru/design-patterns/observer) + - [Состояние](https://refactoring.guru/ru/design-patterns/state) + - [Стратегия](https://refactoring.guru/ru/design-patterns/strategy) + - [Шаблонный метод](https://refactoring.guru/ru/design-patterns/template-method) + - [Посетитель](https://refactoring.guru/ru/design-patterns/visitor) + + +🚀 **_Источник: [Рефакторинг.Гуру](https://refactoring.guru/ru)_** \ No newline at end of file diff --git a/docs/browser/08-rerender_js.md b/docs/browser/08-rerender_js.md new file mode 100644 index 0000000..457eda0 --- /dev/null +++ b/docs/browser/08-rerender_js.md @@ -0,0 +1,103 @@ +--- +sidebar_position: 8 +--- + +# Ререндер страницы в контексте event loop + +Ререндер (перерисовка страницы) и event loop действительно тесно связаны в браузере, хотя происходят на разных уровнях работы движка. + +## 🧠 Что такое event loop (цикл событий) + +Event Loop — это механизм, который координирует выполнение JavaScript и обновление пользовательского интерфейса в браузере. +Он следит за очередями задач (macrotasks и microtasks) и периодически синхронизирует результаты с рендерингом страницы. + +Упрощённо: +1. JS выполняется в однопоточном окружении. +2. Когда движок сталкивается с асинхронной задачей (таймер, fetch, промис), она попадает в очередь. +3. Event loop циклически: + - берёт задачу из очереди макротасков (например, setTimeout, fetch, click), + - выполняет её, + - затем обрабатывает все микротаски (например, .then, queueMicrotask), + - и только после этого может произойти рендер (отрисовка кадра). + +## 🎨 Где тут ререндер страницы +Ререндер (или «перерисовка кадра») происходит между циклами event loop, после того как: +- закончено выполнение всех JS-задач текущей итерации (включая microtasks), +- браузер свободен, +- и наступает момент обновления UI (обычно раз в 16,6 мс для 60 fps). + +Можно представить цикл так: +```text +[ Выполнение JS ] → [ Очередь microtasks ] → [ Пересчёт layout / repaint / composite ] → [ Следующий event loop tick ] +``` + +## 📅 Когда браузер решает перерисовать страницу + +Браузер не будет рендерить страницу посреди выполнения JavaScript — это важно. +Рендеринг откладывается, пока: +- не закончится текущая макротаска, +- не будут выполнены все микротаски (Promise callbacks), +- и браузер решит, что пора обновить UI. + +Например: +```js +console.log("start"); +Promise.resolve().then(() => { + document.body.style.background = "red"; + console.log("microtask done"); +}); +console.log("end"); +``` +Порядок событий: +```text +start +end +microtask done +[перерисовка после microtasks — фон становится красным] +``` + +## ⚙️ Пример с блокировкой рендера + +Если ты сделаешь что-то тяжёлое в JS, например: +```js +while (true) {} // бесконечный цикл +``` +— event loop не сможет дойти до стадии «рендера», и страница «замрёт». +Поэтому анимации, реактивные интерфейсы и плавные переходы требуют, чтобы JS отдавал управление обратно браузеру (через requestAnimationFrame, setTimeout, await, и т.д.). + +## Как requestAnimationFrame вписывается в event loop + +requestAnimationFrame (rAF) — это специальный API, который браузер вызывает перед следующей перерисовкой. +Это позволяет выполнять обновления DOM/Canvas синхронно с циклом рендера, без пропусков кадров. + +```bash +→ JS выполняется +→ rAF callback запланирован +→ microtasks выполняются +→ браузер вызывает rAF callback +→ обновление layout/repaint +→ кадр готов +``` +## 🧩 В контексте фреймворков (React, Vue и т.п.) +Когда React вызывает setState(), обновления не происходят мгновенно: +- Они ставятся в очередь микрозадач или макрозадач (в зависимости от режима). +- После завершения текущего JS-такта React вычисляет новый виртуальный DOM. +- Затем браузер, на этапе рендера event loop, перерисовывает изменённые части UI. + +Таким образом, **event loop управляет моментом**, когда обновления React реально становятся видимыми. + +## 📊 Итоговое резюме + +| Этап | Что делает | +|--------------|---------------------------------------------------------------------| +| Macrotask | Выполняет основную JS-задачу (скрипт, обработчик события и т.д.) | +| Microtasks | Обрабатывает все промисы и микрозадачи | +| Render phase | После JS — браузер вычисляет layout, стили и отрисовывает изменения | +| Next tick | Начинается следующий цикл event loop | + + +### Визуальная схема event loop и рендера (в виде диаграммы) + + + + \ No newline at end of file diff --git a/docs/browser/images/08-rerender-phases.png b/docs/browser/images/08-rerender-phases.png new file mode 100644 index 0000000..04e8b4c Binary files /dev/null and b/docs/browser/images/08-rerender-phases.png differ