Привет. Меня зовут Сергей Сова.
Я наконец-то сделал канал о том, как я негодую... о нашем фронтенде.
На самом деле писать буду о разработке в целом.
Я наконец-то сделал канал о том, как я негодую... о нашем фронтенде.
На самом деле писать буду о разработке в целом.
Почему @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)Всё было хорошо до момента, когда мне понадобилось из такой миддлвары вернуть кастомную ошибку и обработать ее для всех роутов. Пообщавшись с автором, оказалось, что такой функциональности тупо нет. Может быть сейчас уже добавили или я тогда не так изъяснялся, не знаю. Но мне не сильно вкатила идея макросов для роутов, так как это жесткое прибивание гвоздями пути роутера к хендлеру.