Size: a a a

Сова пишет…

2017 August 02
Сова пишет…
Привет. Меня зовут Сергей Сова.
Я наконец-то сделал канал о том, как я негодую... о нашем фронтенде.
На самом деле писать буду о разработке в целом.
источник
2017 September 03
Сова пишет…
Почему @AtomicDesign спасет вашу душу.

Некоторые считают, что этот подход слишком заморочен. Заставляет много думать о расположении элементов, а при усложнении - перемещать его в другие директории. Если спросить Родионова - найдется ещё несколько причин, почему не надо использовать 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 библиотеки экосистемы скорее всего останутся в проекте, а в библиотеку уйдут универсальные для всех проектов компоненты.
источник
2017 November 28
Сова пишет…
Отличное сравнение популярных фреймворков, описаны их преимущества, недостатки и рекомендации к использованию в проектах.

https://www.sitepen.com/blog/2017/11/10/web-frameworks-conclusions/
источник
2018 February 24
Сова пишет…
Ааааааа... Опять увидел обсуждение тс vs флоу. Конечно не смог пройти мимо и хотел было как обычно устроить срач, но не смог: желудок предательски проурчал слово "шаверма".

Многие считают, что typescript это спасение всех жсеров от ошибок, но любой умный человек, пишущий на флоу, понимает, что дело совсем не в типизации. Дело в мемкрософт.

На деле же, с тс немного проще начать писать новый проект (не на реакте конечно). В тс хорошие тулзы и большое сообщество. Но с типизацией и внедрением в готовый проект все очень туго. Как минимум потому, что тс не умеет выводить типы чистого жс, на основе использования кусков кода.

В этом плане флоу выигрывает. Его легко внедрить, он имеет минимум сверхъестественного синтаксиса, ну и с реактом все отлично.
Но сразу оговорюсь, с недавних пор я не большой приверженец типизации в жс. Конечн, она даёт некоторые гарантии, но также добавляет боль. Хотя по сути это просто проверки кода, его правильность, а также защиту от any, никто не гарантирует.
Но находятся люди, которые считают, что использование типизации, а особенно тс, позволяет им не тестировать свой код. Тут сложно что-то сказать, я все таки не психиатр.

Безумное желание все типизировать, похоже на попытку заняться сексом через матрас, ради безопасности.
источник
2018 February 27
Сова пишет…
Пару лет назад, я ради опыта начал писать opensource проект — клон Instagram. Потом разумеется забросил, так как появились важные несуществующие дела.

Примерно месяц назад (в начале февраля 2018) я перезапустил разработку: react, redux, styled-components, @AtomicDesign + деление по фичам. И у меня встал вопрос “на чем писать бæкенд?”. Казалось бы, написать на nodejs (koa / next) самый быстрый и простой вариант, но мне захотелось получить новый опыт. А так как я уже почти год пассивно изучаю Rust, то врядли представится лучший способ прокачаться.

В дальнейшем я планирую писать некоторые отчеты и размышления о разработке Instaclone, как фронтенда так и бæкенда. Ссылки ради ⭐️:
github.com/sergeysova/instaclone-backend.rs
github.com/sergeysova/instaclone
источник
Сова пишет…
Как же обстоят дела с веб-разработкой в расте?
Для начала стоит начать с сайта 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-проекта.
источник
2018 March 29
Сова пишет…
Решил перечитать документацию по API recompose и нашел отличный пример, почему стоит начать ипользовать recompose для компонентов-страниц.

Возможно, когда-нибудь напишу об этом подробнее
источник
2018 July 30
Сова пишет…
На счёт JWT небольшой текст.

Вижу смысл юзать его только для общения между серверами в неких опасных условиях.

Но почему оно того не стоит, можно прочесть по ссылке https://t.me/why_jwt_is_bad
источник
2018 September 09
Сова пишет…
Я слез с Rocket, когда не получилось написать трейт/структуру для указания аутентификации для роута.
Рокет позволяет с помощью макроса на хендлере роута указать миддлвары. О 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 😄.

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.
источник
2018 September 20
Сова пишет…
Сегодня снова начал думать о правильном распределении свободного времени. Есть много разных методик, но я хочу снова попробовать матрицу Эйзенхауэра.
источник
2018 September 29
Сова пишет…
Сделал зеркало для тех кому удобнее читать в телеге

https://t.me/this_week_in_react
источник
2018 October 07
Сова пишет…
Почему директории utils и helpers это свалка?

Начнем с того, как они появляются. Во время разработки проекта, программист старается выносить повторяющиеся куски кода в функции и переиспользовать их. В какой-то момент, в двух разных модулях требуется одна и та же функция, неопытный разработчик решает вынести функцию в отдельный модуль. Но почему-то останавливается на этом решении, создавая директорию/модуль utils или helpers, не думая о будущем этой части программы.

С ростом проекта, количество функций в этой директории растет. Также растет и количество разработчиков в проекте. Функций появляется все больше и больше. Зачастую никто не следит за структурой этих модулей и вполне возможно появление дублирования кода.

Как это решить?
Забудьте о директориях utils и helpers. Эти названия никак не доносят суть содержимого. А из правил чистого кода мы помним, название должно быть однозначным и отражать назначение.
Следует задуматься, почему вообще появилась необходимость в вынесении функции?
Почему они используются в таких разных частях проекта?

Возможно, ответом будет плохая организация кода всего проекта. Если хорошо поисследовать проект можно найти много кода, который достоин вынесения в отдельную библиотеку.
Если же этот код нельзя или не нужно выносить в полноценную библиотеку, его можно вынести в библиотеку внутри проекта. В случае JS, это можно сделать, создав полноценную библиотку внутри lib/.

Такой библиотеке нужно дать осмысленное однозначное название, написать документацию и тесты. Причем собрать в этой библиотеке весь связанный код. Например, вынести все функции работающие с датами во внутреннюю библиотеку lib/datetime. Префикс lib/ позволит избежать конфликтов имен, а также можно будет использовать простые и понятные имена. Конечно же, можно сделать npm scope, чтобы упростить будущую публикацию в npm. Например, @lib/datetime.

Чем это отличается от lib и helpers?
- весь код, выносится в полноценную библиотку с осмысленным названием, документацией и тестами
- lib явно описывает содержимое: это библиотека
- рефакторинг, публикация или удаление этой библиотеки становятся тривиальными задачами
источник
2018 October 15
Сова пишет…
Не так давно в чатах обсуждали (снова) чем отличается фреймворк от библиотеки.

https://dev.to/ben/whats-the-difference-between-a-library-and-a-framework-3blo

В двух словах:
- В случае фреймворка, вы встраиваете свой код в его архитектуру
- Но библиотеку вы самостоятельно встраиваете в собственную архитектуру
источник
2018 October 26
Сова пишет…
Наконец-то, хоть кто-то написал почему снапшот тесты компонентов бесполезны. Хотел уже давно описать, но руки перегорели.

http://foobarbaz.club/why-i-stopped-using-snapshot-testing-with-jest/
источник
2018 October 30
Сова пишет…
Переслано от createStore<🦉>...
Ребята, вы давно просили видео с презентации React SPB Meetup об atomic design и feature slices, но нам запороли запись.
Поэтому я вынес ключевые слайды с комментариями в отдельный канал.

https://t.me/joinchat/AAAAAFcbHfDlRV0eK8kt8w
источник
2018 November 09
Сова пишет…
У меня каждая директория описывает либо одну сущность, либо их набор.

features/ — набор сущностей
features/name — одна сущность
./pages/ — набор сущностей

с файлами похожая штука
./reducer.js — одна сущность
./actions.js — набор сущностей

Вложение директорий определяется вложением сущностей.

— как понять, что есть сущность, а что нет?
— нужно определиться, можно ли с “этим” работать не погружаясь в детали. Можно ли к “этому” обращаться как единой цельной структуре?

страница регистрации сущность? Мы можем ее заимпортить как цельную сущность — да. Можем изменить именно эту страницу — да. Страница цельная сама по себе — да.

ui — сущность? мы можем заимпортить ui и работать с ним в коде — да. Можно ли к нему обращатсья как к цельной структуре — нет(он не несет в себе функциональности, только его части по отдельности ее имеют).
источник
2018 December 06
Сова пишет…
Тем временем, я ухожу из коммерческой разработки на JavaScript.
Возможно, здесь будет больше постов о js и rust
источник
2018 December 08
Сова пишет…
@artalar подкинул статью: https://daneden.me/2018/01/05/subatomic-design-systems/

На первый взгляд выглядит проще Atomic Design, но имеет больше математических концепций.
источник