Привет. Меня зовут Сергей Сова.
Я наконец-то сделал канал о том, как я негодую... о нашем фронтенде.
На самом деле писать буду о разработке в целом.
Я наконец-то сделал канал о том, как я негодую... о нашем фронтенде.
На самом деле писать буду о разработке в целом.
Почему @AtomicDesign спасет вашу душу.
Некоторые считают, что этот подход слишком заморочен. Заставляет много думать о расположении элементов, а при усложнении - перемещать его в другие директории. Если спросить Родионова - найдется ещё несколько причин, почему не надо использовать Atomic Design. В этом посте я хочу рассказать об обратном: как использовать подход Брэда Фроста в React.
В самом начале необходимо понять - нужен ли вашей команде этот архитектурный дизайн. Достаточно ответить на следующие вопросы:
- сколько человек будут разрабатывать фронтенд?
- сколько команд будут использовать ваш код?
- сколько проектов используют один UI дизайн?
Если у вас один небольшой проект, в котором всего два фронтендера - вам не нужен AtomicDesign. Если в вашем проекте около 10 фронтендеров и намечается второй проект - нужно задуматься о внедрении AtomicDesign. Тем более если в вашей компании проекты используют общую библиотеку компонентов или планируется внедрение.
Многие задают мне один и тот же вопрос: "Куда положить компонент X?". Отвечаю сразу для всех компонентов: AtomicDesign - это подход, обеспечивающий вам архитектуру UI компонентов - не более. То есть контейнеры/коннекторы/роутеры вы можете класть в любую директорию, кроме ui. Я всегда рекомендую начать изучение с прочтения книги автора atomicdesign.bradfrost.com, но ниже немного опишу составные части.
Сразу следует понять, что компоненты AtomicDesign — это бизнес-сущности, это то, чем могут оперировать дизайнеры и разработчики вместе. Не надо включать сюда различные таймеры появления блоков или логику переключения вкладок. Пусть даже они у вас описаны в виде компонентов или HOC'ов.
Так почему это все спасает души? Чтобы понять ответ, обратимся к ещё одной теме фронтенда: типизированный javascript. Typescript/Flowtype придумали для наложения определенных ограничений на код, чтобы в дальнейшем его было проще поддерживать и читать. AtomicDesign накладывает ограничения на дизайнеров и фронтендеров, обязывая их общаться на одном языке бизнес-сущностей.
Но необходимо добавить несколько слов о поддержке библиотеки компонентов AtomicKit. В какой-то момент возникает проблема усложнения компонентов, и многие задаются вопросом: "Как же быть, неужели теперь нужно перемещать компонент из атомов в молекулы?" — Нет.
Перед стартом разработки необходимо тщательно проектировать набор компонентов и не менять его предназначения, пока он существует под таким названием. Если же вам необходимо усложнить компонент, добавить в него какие-то элементы - просто создайте ещё один компонент, который будет добавлять то, что вам нужно. Так вы не сломаете совместимость со всей библиотекой и реализуете необходимую вам функциональность. Во время создания второго компонента следует помнить о композиции и рекомендации DRY: не надо копипастить, достаточно использовать уже существующие компоненты.
Некоторые считают, что этот подход слишком заморочен. Заставляет много думать о расположении элементов, а при усложнении - перемещать его в другие директории. Если спросить Родионова - найдется ещё несколько причин, почему не надо использовать Atomic Design. В этом посте я хочу рассказать об обратном: как использовать подход Брэда Фроста в React.
В самом начале необходимо понять - нужен ли вашей команде этот архитектурный дизайн. Достаточно ответить на следующие вопросы:
- сколько человек будут разрабатывать фронтенд?
- сколько команд будут использовать ваш код?
- сколько проектов используют один UI дизайн?
Если у вас один небольшой проект, в котором всего два фронтендера - вам не нужен AtomicDesign. Если в вашем проекте около 10 фронтендеров и намечается второй проект - нужно задуматься о внедрении AtomicDesign. Тем более если в вашей компании проекты используют общую библиотеку компонентов или планируется внедрение.
Многие задают мне один и тот же вопрос: "Куда положить компонент X?". Отвечаю сразу для всех компонентов: AtomicDesign - это подход, обеспечивающий вам архитектуру UI компонентов - не более. То есть контейнеры/коннекторы/роутеры вы можете класть в любую директорию, кроме ui. Я всегда рекомендую начать изучение с прочтения книги автора atomicdesign.bradfrost.com, но ниже немного опишу составные части.
Сразу следует понять, что компоненты AtomicDesign — это бизнес-сущности, это то, чем могут оперировать дизайнеры и разработчики вместе. Не надо включать сюда различные таймеры появления блоков или логику переключения вкладок. Пусть даже они у вас описаны в виде компонентов или HOC'ов.
Так почему это все спасает души? Чтобы понять ответ, обратимся к ещё одной теме фронтенда: типизированный javascript. Typescript/Flowtype придумали для наложения определенных ограничений на код, чтобы в дальнейшем его было проще поддерживать и читать. AtomicDesign накладывает ограничения на дизайнеров и фронтендеров, обязывая их общаться на одном языке бизнес-сущностей.
Но необходимо добавить несколько слов о поддержке библиотеки компонентов AtomicKit. В какой-то момент возникает проблема усложнения компонентов, и многие задаются вопросом: "Как же быть, неужели теперь нужно перемещать компонент из атомов в молекулы?" — Нет.
Перед стартом разработки необходимо тщательно проектировать набор компонентов и не менять его предназначения, пока он существует под таким названием. Если же вам необходимо усложнить компонент, добавить в него какие-то элементы - просто создайте ещё один компонент, который будет добавлять то, что вам нужно. Так вы не сломаете совместимость со всей библиотекой и реализуете необходимую вам функциональность. Во время создания второго компонента следует помнить о композиции и рекомендации DRY: не надо копипастить, достаточно использовать уже существующие компоненты.
Атомы — простейшие компоненты, составляющие части более высокоуровневых компонентов. Могут включать в себя: чистый html, стили. Не могут: состоять из других атомов, иметь логику отображения. Например: поле ввода, подпись, графический значок.
Молекулы — составные компоненты, отражающие одну бизнес-сущность. Могут включать: атомы, html, стили, несложную логику. Не могут включать в себя: другие молекулы, сложную логику, иметь неопределенное поведение. Например: поля форм, заголовки, вкладки, полоса прогресса. Молекулы, как и атомы должны быть максимально универсальными.
Организмы — компоненты, имеющие сложную логику. Самые используемые компоненты в вашем проекте. Содержат в себе: атомы, молекулы, сложную логику и в некоторых случаях поведение, определяющееся извне. Необходимо избегать использования непосредственно стилей в организмах, для этого есть более низкоуровневые компоненты. Например: форма регистрации, карточка статьи, календарь, чат.
Шаблон — разметка для других компонентов. В некоторых случаях у вас будут компоненты, которые просто размещают в себе другие компоненты в определенных местах, - это и есть шаблоны. Шаблоны упростят жизнь, если у вас есть некая разметка с простыми стилями и позиционными компонентами. Может включать в себя: атомы, молекулы, стили, другие шаблоны, простейшую логику. Не может включать в себя: организмы. Шаблоны могут быть как целой страницы, так и её частей. Например: шаблон страницы пользователя/компании, шаблон заголовка сайта (Header).
Страницы — компонент, включащий в себя все остальные компоненты, конечная точка вашего роутера. Страницы обычно располагаются в проекте, используя компоненты из библиотеки.
Экосистемы — наборы компонентов, связанных одной областью использования. Обычно это вложенная директория с той же структурой atoms, molecules, organisms, включающая в себя только компоненты. Которые, например, относятся только к профилю пользователя. При составлении UI библиотеки экосистемы скорее всего останутся в проекте, а в библиотеку уйдут универсальные для всех проектов компоненты.
Молекулы — составные компоненты, отражающие одну бизнес-сущность. Могут включать: атомы, html, стили, несложную логику. Не могут включать в себя: другие молекулы, сложную логику, иметь неопределенное поведение. Например: поля форм, заголовки, вкладки, полоса прогресса. Молекулы, как и атомы должны быть максимально универсальными.
Организмы — компоненты, имеющие сложную логику. Самые используемые компоненты в вашем проекте. Содержат в себе: атомы, молекулы, сложную логику и в некоторых случаях поведение, определяющееся извне. Необходимо избегать использования непосредственно стилей в организмах, для этого есть более низкоуровневые компоненты. Например: форма регистрации, карточка статьи, календарь, чат.
Шаблон — разметка для других компонентов. В некоторых случаях у вас будут компоненты, которые просто размещают в себе другие компоненты в определенных местах, - это и есть шаблоны. Шаблоны упростят жизнь, если у вас есть некая разметка с простыми стилями и позиционными компонентами. Может включать в себя: атомы, молекулы, стили, другие шаблоны, простейшую логику. Не может включать в себя: организмы. Шаблоны могут быть как целой страницы, так и её частей. Например: шаблон страницы пользователя/компании, шаблон заголовка сайта (Header).
Страницы — компонент, включащий в себя все остальные компоненты, конечная точка вашего роутера. Страницы обычно располагаются в проекте, используя компоненты из библиотеки.
Экосистемы — наборы компонентов, связанных одной областью использования. Обычно это вложенная директория с той же структурой atoms, molecules, organisms, включающая в себя только компоненты. Которые, например, относятся только к профилю пользователя. При составлении UI библиотеки экосистемы скорее всего останутся в проекте, а в библиотеку уйдут универсальные для всех проектов компоненты.
Отличное сравнение популярных фреймворков, описаны их преимущества, недостатки и рекомендации к использованию в проектах.
https://www.sitepen.com/blog/2017/11/10/web-frameworks-conclusions/
https://www.sitepen.com/blog/2017/11/10/web-frameworks-conclusions/
SitePen Blog
Web Frameworks: Conclusions
It has come time to read the liner notes and write some conclusions. When we started writing this blog series, we knew that JavaScript/web application frameworks were not easy to summarize.
Ааааааа... Опять увидел обсуждение тс vs флоу. Конечно не смог пройти мимо и хотел было как обычно устроить срач, но не смог: желудок предательски проурчал слово "шаверма".
Многие считают, что typescript это спасение всех жсеров от ошибок, но любой умный человек, пишущий на флоу, понимает, что дело совсем не в типизации. Дело в мемкрософт.
На деле же, с тс немного проще начать писать новый проект (не на реакте конечно). В тс хорошие тулзы и большое сообщество. Но с типизацией и внедрением в готовый проект все очень туго. Как минимум потому, что тс не умеет выводить типы чистого жс, на основе использования кусков кода.
В этом плане флоу выигрывает. Его легко внедрить, он имеет минимум сверхъестественного синтаксиса, ну и с реактом все отлично.
Но сразу оговорюсь, с недавних пор я не большой приверженец типизации в жс. Конечн, она даёт некоторые гарантии, но также добавляет боль. Хотя по сути это просто проверки кода, его правильность, а также защиту от any, никто не гарантирует.
Но находятся люди, которые считают, что использование типизации, а особенно тс, позволяет им не тестировать свой код. Тут сложно что-то сказать, я все таки не психиатр.
Безумное желание все типизировать, похоже на попытку заняться сексом через матрас, ради безопасности.
Многие считают, что typescript это спасение всех жсеров от ошибок, но любой умный человек, пишущий на флоу, понимает, что дело совсем не в типизации. Дело в мемкрософт.
На деле же, с тс немного проще начать писать новый проект (не на реакте конечно). В тс хорошие тулзы и большое сообщество. Но с типизацией и внедрением в готовый проект все очень туго. Как минимум потому, что тс не умеет выводить типы чистого жс, на основе использования кусков кода.
В этом плане флоу выигрывает. Его легко внедрить, он имеет минимум сверхъестественного синтаксиса, ну и с реактом все отлично.
Но сразу оговорюсь, с недавних пор я не большой приверженец типизации в жс. Конечн, она даёт некоторые гарантии, но также добавляет боль. Хотя по сути это просто проверки кода, его правильность, а также защиту от any, никто не гарантирует.
Но находятся люди, которые считают, что использование типизации, а особенно тс, позволяет им не тестировать свой код. Тут сложно что-то сказать, я все таки не психиатр.
Безумное желание все типизировать, похоже на попытку заняться сексом через матрас, ради безопасности.
Пару лет назад, я ради опыта начал писать opensource проект — клон Instagram. Потом разумеется забросил, так как появились важные несуществующие дела.
Примерно месяц назад (в начале февраля 2018) я перезапустил разработку: react, redux, styled-components, @AtomicDesign + деление по фичам. И у меня встал вопрос “на чем писать бæкенд?”. Казалось бы, написать на nodejs (koa / next) самый быстрый и простой вариант, но мне захотелось получить новый опыт. А так как я уже почти год пассивно изучаю Rust, то врядли представится лучший способ прокачаться.
В дальнейшем я планирую писать некоторые отчеты и размышления о разработке Instaclone, как фронтенда так и бæкенда. Ссылки ради ⭐️:
github.com/sergeysova/instaclone-backend.rs
github.com/sergeysova/instaclone
Примерно месяц назад (в начале февраля 2018) я перезапустил разработку: react, redux, styled-components, @AtomicDesign + деление по фичам. И у меня встал вопрос “на чем писать бæкенд?”. Казалось бы, написать на nodejs (koa / next) самый быстрый и простой вариант, но мне захотелось получить новый опыт. А так как я уже почти год пассивно изучаю Rust, то врядли представится лучший способ прокачаться.
В дальнейшем я планирую писать некоторые отчеты и размышления о разработке Instaclone, как фронтенда так и бæкенда. Ссылки ради ⭐️:
github.com/sergeysova/instaclone-backend.rs
github.com/sergeysova/instaclone
GitHub
GitHub - sergeysova/instaclone-backend.rs
Contribute to sergeysova/instaclone-backend.rs development by creating an account on GitHub.
Как же обстоят дела с веб-разработкой в расте?
Для начала стоит начать с сайта arewewebyet.org, он сможет ответить на вопросы о возможности переезда с Rails/Rjango/Flask на Rust, а также обозначить список более-менее рабочих библиотек и фреймворков.
Я спросил в чате @rustlang_ru какую библиотеку/фреймворк мне выбрать в качестве веб-сервера для своего проекта, в ответ получил много предложений, но настоятельно рекомендовали hyper.rs.
Что-ж, это низкоуровневая библиотека, не имеющая в комплекте роутинга, но с возможностью асинхронщины на futures. Результат моих попыток есть в https://github.com/sergeysova/instaclone-backend.rs/tree/feature/hyper. Я практически сразу уткнулся в необходимость написания своего роутера, так как хэндлить роуты вроде /users/:user_id библиотека не умеет. Такой подход мгновенно отбил у меня желание писать дальше.
Следующим кандидатом выступил фреймворк Fanta docs.rs/crate/fanta. Этот подход мне понравился сильно больше, так как имел в своем арсенале всё, что нужно для работы с базой и http-запросами. Fanta построена на совместной работе serde.rs для сериализации, tokio.rs для работы с сетью, diesel.rs для работы с базой. Мне показалось, что я сделал правильный выбор, но молодость фреймворка сказалась также очень быстро. Пришлось писать слишком много сервисного кода, и слишком мало бизнес-логики. Буквально дальше сгенеренного приложения не зашло. https://github.com/sergeysova/instaclone-backend.rs/tree/feature/fanta
После очередного холивара в чате Rust, я обратил внимание на rocket.rs, который до этого выкинул из поля зрения, по причине работе только на nightly версии rustc. В этот раз, я решил рассмотреть его поближе. И о чудо, оно заработало, очень просто и приятно. Весь бойлерплейтный код скрывается в макросах
Имеется валидация параметров, входных данных, параметров query, cookies прямо из коробки да по структурам раста, и для этого не нужно писать лишнего кода, просто указать аргументы функции. Меня всё это очень сильно подкупило. Весьма неплохие гайды и документация по API сделали своё дело, за пару дней я написал несложное приложение с двумя роутами, прикрутил базу PostgreSQL с помощью diesel.rs и впридачу получил красивый логгер для отладки. Ко всему прочему, rocket из коробки имеет гайд по настройке пула соединений с базой на основе r2d2 docs.rs/crate/r2d2 и это прекрасно.
Вердикт: продолжаю использовать rocket + diesel для своего pet-проекта.
Для начала стоит начать с сайта arewewebyet.org, он сможет ответить на вопросы о возможности переезда с Rails/Rjango/Flask на Rust, а также обозначить список более-менее рабочих библиотек и фреймворков.
Я спросил в чате @rustlang_ru какую библиотеку/фреймворк мне выбрать в качестве веб-сервера для своего проекта, в ответ получил много предложений, но настоятельно рекомендовали hyper.rs.
Что-ж, это низкоуровневая библиотека, не имеющая в комплекте роутинга, но с возможностью асинхронщины на futures. Результат моих попыток есть в https://github.com/sergeysova/instaclone-backend.rs/tree/feature/hyper. Я практически сразу уткнулся в необходимость написания своего роутера, так как хэндлить роуты вроде /users/:user_id библиотека не умеет. Такой подход мгновенно отбил у меня желание писать дальше.
Следующим кандидатом выступил фреймворк Fanta docs.rs/crate/fanta. Этот подход мне понравился сильно больше, так как имел в своем арсенале всё, что нужно для работы с базой и http-запросами. Fanta построена на совместной работе serde.rs для сериализации, tokio.rs для работы с сетью, diesel.rs для работы с базой. Мне показалось, что я сделал правильный выбор, но молодость фреймворка сказалась также очень быстро. Пришлось писать слишком много сервисного кода, и слишком мало бизнес-логики. Буквально дальше сгенеренного приложения не зашло. https://github.com/sergeysova/instaclone-backend.rs/tree/feature/fanta
После очередного холивара в чате Rust, я обратил внимание на rocket.rs, который до этого выкинул из поля зрения, по причине работе только на nightly версии rustc. В этот раз, я решил рассмотреть его поближе. И о чудо, оно заработало, очень просто и приятно. Весь бойлерплейтный код скрывается в макросах
#[get(“/users/<user_id>”)]Имеется валидация параметров, входных данных, параметров query, cookies прямо из коробки да по структурам раста, и для этого не нужно писать лишнего кода, просто указать аргументы функции. Меня всё это очень сильно подкупило. Весьма неплохие гайды и документация по API сделали своё дело, за пару дней я написал несложное приложение с двумя роутами, прикрутил базу PostgreSQL с помощью diesel.rs и впридачу получил красивый логгер для отладки. Ко всему прочему, rocket из коробки имеет гайд по настройке пула соединений с базой на основе r2d2 docs.rs/crate/r2d2 и это прекрасно.
Вердикт: продолжаю использовать rocket + diesel для своего pet-проекта.
На счёт JWT небольшой текст.
Вижу смысл юзать его только для общения между серверами в неких опасных условиях.
Но почему оно того не стоит, можно прочесть по ссылке https://t.iss.one/why_jwt_is_bad
Вижу смысл юзать его только для общения между серверами в неких опасных условиях.
Но почему оно того не стоит, можно прочесть по ссылке https://t.iss.one/why_jwt_is_bad
Я слез с Rocket, когда не получилось написать трейт/структуру для указания аутентификации для роута.
Рокет позволяет с помощью макроса на хендлере роута указать миддлвары. О request guards можно почитать здесь.
Приблизительно, как это работает, макрос создает функцию которая будет вызываться каждый раз при запросе в указанный роут. В этой функции генерируется весь обслуживающий код, в том числе специальный вызов написанного хендлера с параметрами. Но так как Rust позволяет обратиться к дженерик типу (`T::some_method()`), перед вызовом хендлера, вызывает методы у типов его аргументов (`AuthOptional::from_request(&req)`).
Я хотел указывать там аутентификаци: опциональную или требуемую.
Опциональная: хендлер сам решает, что ему делать в случае отсутствия аутентификации. Чуть ли не через простой
Требуемая: миддлвара пропускает в хендлер только аутентифицированные запросы и кладет куда-то инстанс юзера, для удобства. Анонимам делает отлуп с
В nodejs это решается просто и удобно:
Всё было хорошо до момента, когда мне понадобилось из такой миддлвары вернуть кастомную ошибку и обработать ее для всех роутов. Пообщавшись с автором, оказалось, что такой функциональности тупо нет. Может быть сейчас уже добавили или я тогда не так изъяснялся, не знаю. Но мне не сильно вкатила идея макросов для роутов, так как это жесткое прибивание гвоздями пути роутера к хендлеру.
Рокет позволяет с помощью макроса на хендлере роута указать миддлвары. О request guards можно почитать здесь.
#[post("/search")]
fn search_handler(auth: AuthOptional) -> ... { ... }Приблизительно, как это работает, макрос создает функцию которая будет вызываться каждый раз при запросе в указанный роут. В этой функции генерируется весь обслуживающий код, в том числе специальный вызов написанного хендлера с параметрами. Но так как Rust позволяет обратиться к дженерик типу (`T::some_method()`), перед вызовом хендлера, вызывает методы у типов его аргументов (`AuthOptional::from_request(&req)`).
Я хотел указывать там аутентификаци: опциональную или требуемую.
Опциональная: хендлер сам решает, что ему делать в случае отсутствия аутентификации. Чуть ли не через простой
if session.is_auth().Требуемая: миддлвара пропускает в хендлер только аутентифицированные запросы и кладет куда-то инстанс юзера, для удобства. Анонимам делает отлуп с
401 и для этого не надо писать лишнего кода.В nodejs это решается просто и удобно:
router.post('/search', authOptional(), searchHandler)
router.post('/search/private', authRequired(), searchPrivateHandler)Всё было хорошо до момента, когда мне понадобилось из такой миддлвары вернуть кастомную ошибку и обработать ее для всех роутов. Пообщавшись с автором, оказалось, что такой функциональности тупо нет. Может быть сейчас уже добавили или я тогда не так изъяснялся, не знаю. Но мне не сильно вкатила идея макросов для роутов, так как это жесткое прибивание гвоздями пути роутера к хендлеру.
Итак actix.
Сам actix — фреймворк построенный на модели акторов. Я не вникал в эту модель и паттерны, перед тем, как начать писать на actix-web.
Actix по другому строит роутинг. Более привычным способом для разработчиков nodejs 😄.
Сами хендлеры не заворачиваются в макросы и остаются обычными функциями от аргументов. Но большинство хендлеров имеют тип
Но на самом деле, хендлер это тоже трейт —
Итак, что это даёт? Actix также как и Rocket умеет принимать хендлеры с кастомными аргументами.
Типичный хендлер выглядит так.
Но количество аргументов можно расширить через кортеж.
С таким подходом, реализовать отлуп required аутентификации становится в разы проще. Я написал две простеньких структуры
Ссылка на код в howtocards
Пример использования
Я не очень внимательно читал документацию по экстракторам и долго пытался понять как мне реализовать эту фичу. Пришлось связаться с автором actix и выяснить тонкости. Изначально, я хотел реализовать свой
Посмотреть примеры работы с actix можно посмотреть в репозитории sentry в директории server.
Также интересные подходы в написании веб-сервера есть в исходниках crates.io.
Сам actix — фреймворк построенный на модели акторов. Я не вникал в эту модель и паттерны, перед тем, как начать писать на actix-web.
Actix по другому строит роутинг. Более привычным способом для разработчиков nodejs 😄.
app.resource("/account", |route| {
route.method(Method::POST).with(account_handler)
});Сами хендлеры не заворачиваются в макросы и остаются обычными функциями от аргументов. Но большинство хендлеров имеют тип
Fn(..) -> impl Responder, это значит, что функция должна вернуть любой тип имплементирующий трейт Responder. Разработчики actix-web реализовали этот трейт для всех стандартных типов.Но на самом деле, хендлер это тоже трейт —
Handler (ссылка). В этом файле есть имплементация Handler для функции.Итак, что это даёт? Actix также как и Rocket умеет принимать хендлеры с кастомными аргументами.
Типичный хендлер выглядит так.
fn common_handler(req: HttpRequest<State>) -> impl Responder { ... }Но количество аргументов можно расширить через кортеж.
fn custom((req, auth, query): (HttpRequest<State>, Auth, Query<Info>)) -> impl Responder { ... }Auth, Query<T> называются Extractors и их задача вытаскивать что-то из запроса в хендлер, тоже своеобразный middleware. Хотя actix имеет полноценные middlewares, экстракторы очень полезны, так как позволяют делать асинхронные экстракторы и выполнять отлуп запроса, до исполнения хендлера.С таким подходом, реализовать отлуп required аутентификации становится в разы проще. Я написал две простеньких структуры
Auth и AuthOptional. Обе реализуют трейт FromRequest<State>.Auth делает отлуп запроса, если пользователь пришел без аутентификации или с дохлым токеном (и т.д.). AuthOptional просто дергает метод Auth::from_request но не делает отлуп пользователю, а заворачивает сессию в Option.Ссылка на код в howtocards
Пример использования
Я не очень внимательно читал документацию по экстракторам и долго пытался понять как мне реализовать эту фичу. Пришлось связаться с автором actix и выяснить тонкости. Изначально, я хотел реализовать свой
SessionBackend и пытаться крутиться вокруг него.Посмотреть примеры работы с actix можно посмотреть в репозитории sentry в директории server.
Также интересные подходы в написании веб-сервера есть в исходниках crates.io.
Сова пишет… via @like
Почему директории utils и helpers это свалка?
Начнем с того, как они появляются. Во время разработки проекта, программист старается выносить повторяющиеся куски кода в функции и переиспользовать их. В какой-то момент, в двух разных модулях требуется одна и та же функция, неопытный разработчик решает вынести функцию в отдельный модуль. Но почему-то останавливается на этом решении, создавая директорию/модуль utils или helpers, не думая о будущем этой части программы.
С ростом проекта, количество функций в этой директории растет. Также растет и количество разработчиков в проекте. Функций появляется все больше и больше. Зачастую никто не следит за структурой этих модулей и вполне возможно появление дублирования кода.
Как это решить?
Забудьте о директориях utils и helpers. Эти названия никак не доносят суть содержимого. А из правил чистого кода мы помним, название должно быть однозначным и отражать назначение.
Следует задуматься, почему вообще появилась необходимость в вынесении функции?
Почему они используются в таких разных частях проекта?
Возможно, ответом будет плохая организация кода всего проекта. Если хорошо поисследовать проект можно найти много кода, который достоин вынесения в отдельную библиотеку.
Если же этот код нельзя или не нужно выносить в полноценную библиотеку, его можно вынести в библиотеку внутри проекта. В случае JS, это можно сделать, создав полноценную библиотку внутри lib/.
Такой библиотеке нужно дать осмысленное однозначное название, написать документацию и тесты. Причем собрать в этой библиотеке весь связанный код. Например, вынести все функции работающие с датами во внутреннюю библиотеку lib/datetime. Префикс lib/ позволит избежать конфликтов имен, а также можно будет использовать простые и понятные имена. Конечно же, можно сделать npm scope, чтобы упростить будущую публикацию в npm. Например, @lib/datetime.
Чем это отличается от lib и helpers?
- весь код, выносится в полноценную библиотку с осмысленным названием, документацией и тестами
- lib явно описывает содержимое: это библиотека
- рефакторинг, публикация или удаление этой библиотеки становятся тривиальными задачами
Начнем с того, как они появляются. Во время разработки проекта, программист старается выносить повторяющиеся куски кода в функции и переиспользовать их. В какой-то момент, в двух разных модулях требуется одна и та же функция, неопытный разработчик решает вынести функцию в отдельный модуль. Но почему-то останавливается на этом решении, создавая директорию/модуль utils или helpers, не думая о будущем этой части программы.
С ростом проекта, количество функций в этой директории растет. Также растет и количество разработчиков в проекте. Функций появляется все больше и больше. Зачастую никто не следит за структурой этих модулей и вполне возможно появление дублирования кода.
Как это решить?
Забудьте о директориях utils и helpers. Эти названия никак не доносят суть содержимого. А из правил чистого кода мы помним, название должно быть однозначным и отражать назначение.
Следует задуматься, почему вообще появилась необходимость в вынесении функции?
Почему они используются в таких разных частях проекта?
Возможно, ответом будет плохая организация кода всего проекта. Если хорошо поисследовать проект можно найти много кода, который достоин вынесения в отдельную библиотеку.
Если же этот код нельзя или не нужно выносить в полноценную библиотеку, его можно вынести в библиотеку внутри проекта. В случае JS, это можно сделать, создав полноценную библиотку внутри lib/.
Такой библиотеке нужно дать осмысленное однозначное название, написать документацию и тесты. Причем собрать в этой библиотеке весь связанный код. Например, вынести все функции работающие с датами во внутреннюю библиотеку lib/datetime. Префикс lib/ позволит избежать конфликтов имен, а также можно будет использовать простые и понятные имена. Конечно же, можно сделать npm scope, чтобы упростить будущую публикацию в npm. Например, @lib/datetime.
Чем это отличается от lib и helpers?
- весь код, выносится в полноценную библиотку с осмысленным названием, документацией и тестами
- lib явно описывает содержимое: это библиотека
- рефакторинг, публикация или удаление этой библиотеки становятся тривиальными задачами
Не так давно в чатах обсуждали (снова) чем отличается фреймворк от библиотеки.
https://dev.to/ben/whats-the-difference-between-a-library-and-a-framework-3blo
В двух словах:
- В случае фреймворка, вы встраиваете свой код в его архитектуру
- Но библиотеку вы самостоятельно встраиваете в собственную архитектуру
https://dev.to/ben/whats-the-difference-between-a-library-and-a-framework-3blo
В двух словах:
- В случае фреймворка, вы встраиваете свой код в его архитектуру
- Но библиотеку вы самостоятельно встраиваете в собственную архитектуру
DEV Community
What's the difference between a library and a framework?
Having a look at this comment by @kayis from another thread, I'm wondering if you agree with this st...
Наконец-то, хоть кто-то написал почему снапшот тесты компонентов бесполезны. Хотел уже давно описать, но руки перегорели.
https://foobarbaz.club/why-i-stopped-using-snapshot-testing-with-jest/
https://foobarbaz.club/why-i-stopped-using-snapshot-testing-with-jest/