HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>До сих пор мы пользовались фреймворком Express как чёрным ящиком. Что, кстати, характеризует его как хорошую абстракцию. Но помимо очевидного внешнего поведения у микрофреймворков есть ещё одно интересное свойство. Давайте зададим себе вопрос: какими качествами должен обладать хороший фреймворк?</p>
1 <p>До сих пор мы пользовались фреймворком Express как чёрным ящиком. Что, кстати, характеризует его как хорошую абстракцию. Но помимо очевидного внешнего поведения у микрофреймворков есть ещё одно интересное свойство. Давайте зададим себе вопрос: какими качествами должен обладать хороший фреймворк?</p>
2 <p>Самое очевидное и важное - это концептуальный дизайн, который определяет то, с какими абстракциями мы имеем дело. Бывают фреймворки, в которых абстракции не очень удачные, и разработка на них обрастает<strong>случайной сложностью</strong>. С другой стороны, в вебе более-менее выработан единый подход к организации серверных фреймворков. Доминирующей является архитектура MVC, с которой мы и работаем. Controller - контроллеры это наши обработчики, View - это шаблоны, а Model - это наши сущности и бизнес-логика.</p>
2 <p>Самое очевидное и важное - это концептуальный дизайн, который определяет то, с какими абстракциями мы имеем дело. Бывают фреймворки, в которых абстракции не очень удачные, и разработка на них обрастает<strong>случайной сложностью</strong>. С другой стороны, в вебе более-менее выработан единый подход к организации серверных фреймворков. Доминирующей является архитектура MVC, с которой мы и работаем. Controller - контроллеры это наши обработчики, View - это шаблоны, а Model - это наши сущности и бизнес-логика.</p>
3 <p><em>Замечание. Исторически MVC, который принят в вебе, сильно отличается от первоначального MVC, основное применение которого было толстые клиенты. В литературе можно встретить обозначение "MVC v2" для веб версии.</em></p>
3 <p><em>Замечание. Исторически MVC, который принят в вебе, сильно отличается от первоначального MVC, основное применение которого было толстые клиенты. В литературе можно встретить обозначение "MVC v2" для веб версии.</em></p>
4 <p>Если предположить, что с дизайном всё в порядке, то на сцену выходят более утилитарные качества:</p>
4 <p>Если предположить, что с дизайном всё в порядке, то на сцену выходят более утилитарные качества:</p>
5 <ul><li>Гибкость</li>
5 <ul><li>Гибкость</li>
6 <li>Расширяемость</li>
6 <li>Расширяемость</li>
7 <li>Модульность</li>
7 <li>Модульность</li>
8 </ul><p>В этом месте мы поговорим о расширяемости, которая в свою очередь приводит к модульности. Рассмотрим самый простой пример - функции. Как можно расширить поведение функции?</p>
8 </ul><p>В этом месте мы поговорим о расширяемости, которая в свою очередь приводит к модульности. Рассмотрим самый простой пример - функции. Как можно расширить поведение функции?</p>
9 <h2>Wrapping</h2>
9 <h2>Wrapping</h2>
10 <p>Нет ничего проще, чем расширять поведение функции. Нужно написать новую функцию, в которой используется первоначальная. Единственное условие, которое нужно соблюсти, это совпадение входов этих функций (количество и тип аргументов) и выходов (тип выхода). В таком случае код, использующий вашу обёрнутую функцию, даже не сможет догадаться о том, что она обёрнута, ну а главное, что его не нужно переписывать, ведь интерфейс функции не поменялся, хотя и появилось новое поведение. Такой способ так же называют декорированием, и в справочниках по шаблонам проектирования описывают как "паттерн декоратор".</p>
10 <p>Нет ничего проще, чем расширять поведение функции. Нужно написать новую функцию, в которой используется первоначальная. Единственное условие, которое нужно соблюсти, это совпадение входов этих функций (количество и тип аргументов) и выходов (тип выхода). В таком случае код, использующий вашу обёрнутую функцию, даже не сможет догадаться о том, что она обёрнута, ну а главное, что его не нужно переписывать, ведь интерфейс функции не поменялся, хотя и появилось новое поведение. Такой способ так же называют декорированием, и в справочниках по шаблонам проектирования описывают как "паттерн декоратор".</p>
11 <p>По похожей идее устроен Express, а точнее connect, который является ядром микрофреймворка Express.</p>
11 <p>По похожей идее устроен Express, а точнее connect, который является ядром микрофреймворка Express.</p>
12 <h2>Connect</h2>
12 <h2>Connect</h2>
13 <h2>Middleware</h2>
13 <h2>Middleware</h2>
14 <p>Connect представляет из себя механизм, который расширяется функциями, называемыми middleware. Каждый раз, когда мы используем use, очередная middleware добавляется в общую очередь. В конечном счёте получается объект, наполненный мидлварами. Каждый запрос, отправляемый на обработку в connect, проходит через цепочку этих middleware пока не наткнётся на терминальную мидлвару.</p>
14 <p>Connect представляет из себя механизм, который расширяется функциями, называемыми middleware. Каждый раз, когда мы используем use, очередная middleware добавляется в общую очередь. В конечном счёте получается объект, наполненный мидлварами. Каждый запрос, отправляемый на обработку в connect, проходит через цепочку этих middleware пока не наткнётся на терминальную мидлвару.</p>
15 <p>В свою очередь каждая мидлвара принимает на вход три параметра: request, response и next. Она может поменять их и в конце должна вызвать next для передачи управления следующей по списку мидлваре. В этом и заключается вся мощь микрофреймворков. Удачный дизайн позволяет легко разбивать систему на модули-мидлвары и расширять за счёт мидлвар, которые, в большом количестве, пишут сторонние разработчики.</p>
15 <p>В свою очередь каждая мидлвара принимает на вход три параметра: request, response и next. Она может поменять их и в конце должна вызвать next для передачи управления следующей по списку мидлваре. В этом и заключается вся мощь микрофреймворков. Удачный дизайн позволяет легко разбивать систему на модули-мидлвары и расширять за счёт мидлвар, которые, в большом количестве, пишут сторонние разработчики.</p>
16 <p>В Connect нет ничего кроме метода use добавляющего очередную мидлвару в стек.</p>
16 <p>В Connect нет ничего кроме метода use добавляющего очередную мидлвару в стек.</p>
17 <h2>Mount middleware</h2>
17 <h2>Mount middleware</h2>
18 <p>Самое интересное в Connect, что обработчики конкретных маршрутов - это тоже, всего-навсего, мидлвары. Их особенностью является привязка к конкретному маршруту, в отличие от мидлвар, которые выполняются для всех запросов.</p>
18 <p>Самое интересное в Connect, что обработчики конкретных маршрутов - это тоже, всего-навсего, мидлвары. Их особенностью является привязка к конкретному маршруту, в отличие от мидлвар, которые выполняются для всех запросов.</p>
19 <p>Такие мидлвары позволяют реализовывать базовый роутинг без привязки к конкретному глаголу http и без поддержки динамических маршрутов. В Express роутинг реализован без привязки к Mount Middlewares.</p>
19 <p>Такие мидлвары позволяют реализовывать базовый роутинг без привязки к конкретному глаголу http и без поддержки динамических маршрутов. В Express роутинг реализован без привязки к Mount Middlewares.</p>
20 <h2>Terminate</h2>
20 <h2>Terminate</h2>
21 <p>Но далеко не всегда мы хотим двигаться вглубь. Более того, в какой-то момент одна из мидлвар должна взять обработку на себя.</p>
21 <p>Но далеко не всегда мы хотим двигаться вглубь. Более того, в какой-то момент одна из мидлвар должна взять обработку на себя.</p>
22 <p>У такого поведения, когда есть цепочка функций и любая из них в процессе обработки может принять решение остановки цепочки и возврата ответа, есть имя. Такие цепочки называют chain responsibility, и это тоже паттерн.</p>
22 <p>У такого поведения, когда есть цепочка функций и любая из них в процессе обработки может принять решение остановки цепочки и возврата ответа, есть имя. Такие цепочки называют chain responsibility, и это тоже паттерн.</p>