<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="./rss/styles.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Блог Черкашина Александра | cherkashin.dev</title><description>Блог Черкашина Александра | cherkashin.dev</description><link>https://cherkashin.dev/</link><language>ru-RU</language><lastBuildDate>Mon, 13 Apr 2026 09:00:10 GMT</lastBuildDate><atom:link href="https://cherkashin.dev/rss.xml" rel="self" type="application/rss+xml"/><item><title>💪 Боремся с ютубом за внимание</title><link>https://cherkashin.dev/posts/474/</link><guid isPermaLink="true">https://cherkashin.dev/posts/474/</guid><description>💪 Боремся с ютубом за внимание

Вчера я вернулся из отпуска, отдохнул замечательно. Прилетел на отдых и просто ел, спал, лежал и плавал, никакого тебе стресса, единственная забота — что бы такое съесть на шведском столе.

Ну если не считать уведомления из налоговой. От каждого их письма я вздрагиваю, после того, как м...</description><pubDate>Mon, 13 Apr 2026 09:00:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;💪 Боремся с ютубом за внимание&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Вчера я вернулся из отпуска, отдохнул замечательно. Прилетел на отдых и просто ел, спал, лежал и плавал, никакого тебе стресса, единственная забота — что бы такое съесть на шведском столе.&lt;/p&gt;
&lt;p&gt;Ну если не считать уведомления из налоговой. От каждого их письма я вздрагиваю, после того, как мне пришлось им заплатить 83 000р из-за неправильно оформленного патента 😅.&lt;/p&gt;
&lt;p&gt;Я не читал и не смотрел новостные видосы, не читал телеграмм каналы||, ну почти||. Но в те моменты, когда мне нужно было найти что-то на Ютубе, я открывал главную страницу и видел его рекомендации… И тут сразу вижу, что произошло в мире, что я что-то пропускаю, там новость интересная, а там чувак рассказывает, как он продуктивность свою увеличил в 10 раз, а ещё новый трейлер нового Человека Паука вышел.&lt;/p&gt;
&lt;p&gt;Блин, всё такое интересное, хочется сразу посмотреть, в общем, ютуб полностью захватывает внимание, через 10 минут я закрываю вкладку и только потом вспоминаю, зачем я вообще туда заходил.&lt;/p&gt;
&lt;p&gt;Пару месяцев я &lt;a href=&quot;https://t.me/cherkashindev/429&quot;&gt;писал про One Sec&lt;/a&gt;, а сегодня расскажу про подходы, чтобы отключить навязчивые рекомендации Ютуба.&lt;/p&gt;
&lt;p&gt;Я нашел два подхода:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;браузерные расширения&lt;/li&gt;
&lt;li&gt;встроенный способ на ютубе&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я пока попробовал первый вариант — &lt;a href=&quot;https://chromewebstore.google.com/detail/unhook-remove-youtube-rec/khncfooichmfjbepaaaebmommgaepoid&quot;&gt;расширение Unhook&lt;/a&gt;, оно помогает отключить все рекомендации ютуба:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;главная страница будет просто пуста — просто чёрный экран (как на скрине)&lt;/li&gt;
&lt;li&gt;при просмотре видео никаких панелей с рекомендаций, никаких отвлечений&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Второй подход — удалить всю историю ютуба, в этом случае главная страница будет также пуста. Этот подход пока не пробовал, &lt;a href=&quot;https://www.youtube.com/watch?v=ZdNIBeynCIk&quot;&gt;но вот здесь&lt;/a&gt; наши индийские друзья уже всё объяснили.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❤️ — если ютуб также захватывает ваше внимание&lt;/li&gt;
&lt;li&gt;👍 — если вы уже пользуетесь описанными подходами&lt;/li&gt;
&lt;li&gt;🔥 — если вы не против, чтобы ютуб вас отвлекал&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#productivity&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-474-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-474-1.jpg"/></item><item><title>Я собираюсь в свой первый отпуск в этом году, а значит пора всё-таки немного рассказать, как я…</title><link>https://cherkashin.dev/posts/464/</link><guid isPermaLink="true">https://cherkashin.dev/posts/464/</guid><description>Я собираюсь в свой первый отпуск в этом году, а значит пора всё-таки немного рассказать, как я провел предыдущий отпуск.

Прошлой весной мы летали в Дубай, как хорошо, что мы решили полететь туда в том году, в этом я бы уже не рискнул.

Наш рейс задержали на пару часов, поэтому когда мы прилетели, то встряли в жёсткую ...</description><pubDate>Thu, 02 Apr 2026 08:13:25 GMT</pubDate><content:encoded>&lt;p&gt;Я собираюсь в свой первый отпуск в этом году, а значит пора всё-таки немного рассказать, как я провел предыдущий отпуск.&lt;/p&gt;
&lt;p&gt;Прошлой весной мы летали в Дубай, как хорошо, что мы решили полететь туда в том году, в этом я бы уже не рискнул.&lt;/p&gt;
&lt;p&gt;Наш рейс задержали на пару часов, поэтому когда мы прилетели, то встряли в жёсткую пробку, и до отеля ехали как черепахи. Остановились в &lt;a href=&quot;https://yandex.com/maps/-/CPbEMY7e&quot;&gt;Ja Ocean View Hotel&lt;/a&gt;, отель выбрали из-за вида на Персидский залив и колесо обозрения, он просто бомбический, особенно ночью, когда всё сияет.&lt;/p&gt;
&lt;p&gt;Когда мы заселились было уже темно, поэтому пошли сразу гулять по набережной, и рты у нас приоткрылись, тут и море, и набережная и высотки и это всё сияет в ночи. Мы немного пожалели, что мы приехали именно сюда. Подумали: ну всё, красивее уже, наверное, не будет, можно больше и не путешествовать 😅. Конечно, ко всему этому мы привыкли за пару дней.&lt;/p&gt;
&lt;p&gt;На следующий день у моей дорогой жены был день рождения и мы пошли &lt;a href=&quot;https://yandex.com/maps/-/CPbEYT-e&quot;&gt;на колесо обозрения&lt;/a&gt;. Виды там, конечно, шикарные, а ещё это огромное колесо стоит на искусственном острове.&lt;/p&gt;
&lt;p&gt;Потом заглянули в очень красивый Старбакс. Когда я куда-то еду, я всегда захожу в Старбакс с надеждой, что там будет нормальный американо или капучино, но пока удача мне не улыбнулась, вкусный у них только холодный кофе.&lt;/p&gt;
&lt;p&gt;Потом мы поехали шопиться, это был, наверно, первый раз, когда мы столько времени за весь отпуск провели слоняясь по торговым центрам 😅.&lt;/p&gt;
&lt;p&gt;Вообще, в этот раз мы уговаривали себя не пытаться посмотреть всё всё всё, что только возможно, хотя в Дубае это было достаточно сложно. Но мы вроде как справились, посетили примерно половину из того что планировали изначально. Этому ещё помогло то, что я заболел после первого же купания. Я вообще люблю болеть в отпуске.&lt;/p&gt;
&lt;p&gt;Вообще море в Дубае так себе. Либо это ощущение после Египта, где море прям шикарное, либо дело в искусственных островах, из-за которых, вода застаивается Было ощущение, что мы скорее на речке, чем на море.&lt;/p&gt;
&lt;p&gt;Из того, что успели посмотреть в Дубае:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://yandex.com/maps/-/CPbEYT-e&quot;&gt;Колесо обозрения&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Смотровую на пальме — &lt;a href=&quot;https://yandex.com/maps/-/CPbEeW5e&quot;&gt;The View at the Palm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://yandex.com/maps/-/CPbEiA5U&quot;&gt;Световое шоу у Бурдж Халифы&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://yandex.com/maps/-/CPbEiUo9&quot;&gt;Потерялись в Дубай Молле&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Покатались на Катере по Персидскому заливу&lt;/li&gt;
&lt;li&gt;Нашли “настоящий” и “поддельный” дубайский шоколад&lt;/li&gt;
&lt;li&gt;Съездили на экскурсию в Абу-Даби
- &lt;a href=&quot;https://yandex.com/maps/-/CPbEmJNP&quot;&gt;Пробежались по Лувру&lt;/a&gt;
- &lt;a href=&quot;https://yandex.com/maps/-/CPbEmGlX&quot;&gt;Заехали в Президентский Дворец&lt;/a&gt;
- &lt;a href=&quot;https://yandex.com/maps/-/CPbEmLNW&quot;&gt;Походили с открытым ртом по мечети шейха Зайда&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Возвращаюсь к Старбаксу, в старом городе, есть очень &lt;a href=&quot;https://yandex.com/maps/-/CPbEuBMW&quot;&gt;колоритный Старбакс&lt;/a&gt;, ну, конечно, и очереди там соответствующие, и нам пришлось минут 20 ждать пока пара китаянок сделает миллион фоток, прежде чем мы смогли сфоткаться.&lt;/p&gt;
&lt;p&gt;Мы ездили в Рамадан, но туристы скорее всего ничего и не заметят. Единственное, старались не пить воду у всех на виду. Март отличный месяц для Дубая, не очень жарко, легкий ветерок, очень комфортно в течении всего дня. &lt;/p&gt;
&lt;p&gt;Под конец отпуска, я почуствовал, будто зарядился от всего что тут окружает. Прямо появляется желание взять и фигачить. Мне кажется так действуют эти солнечные дни, особенно когда после зимы и зимней хандры ты попадаешь в место где куча света и невероятная красота.&lt;/p&gt;
&lt;p&gt;Тут невероятно чисто, никакого мусора. Яблоки сложены одно к одному как египетские пирамиды, морковки выложены вряд. Хотя, так, конечно, не везде, мы ездили в старые районы, где есть ещё тот старый Дубай, и там совсём всё не дорого богато.&lt;/p&gt;
&lt;p&gt;Мне кажется Курск в этом плане угнетает, нельзя вот так выйти и насладиться красотой. Впитать немного энергии из вне, приходится вывозить на морально волевых, или сваливать в отпуск на подзарядку 😄.&lt;/p&gt;
&lt;p&gt;Рассказывайте:&lt;/p&gt;
&lt;p&gt;🔥 — тоже уже были в отпуске в этом году
🤨 — ещё не успели отдохнуть
❤️ — желаете мне не заболеть в этот раз&lt;/p&gt;
&lt;p&gt;#vacation&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-464-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-464-1.jpg"/></item><item><title>Вчера говорю жене: так и не придумал какую шутку написать на 1 апреля</title><link>https://cherkashin.dev/posts/463/</link><guid isPermaLink="true">https://cherkashin.dev/posts/463/</guid><description>Вчера говорю жене: так и не придумал какую шутку написать на 1 апреля

Жена: какие шутки? время сейчас такое, не до шуток совсем

Я: Отлично, спасибо так и напишу

Надеюсь сегодня обойдётся без дурацких новостей шуток.</description><pubDate>Wed, 01 Apr 2026 07:25:10 GMT</pubDate><content:encoded>&lt;p&gt;Вчера говорю жене: так и не придумал какую шутку написать на 1 апреля&lt;/p&gt;
&lt;p&gt;Жена: какие шутки? время сейчас такое, не до шуток совсем&lt;/p&gt;
&lt;p&gt;Я: Отлично, спасибо так и напишу&lt;/p&gt;
&lt;p&gt;Надеюсь сегодня обойдётся без дурацких &lt;del&gt;новостей&lt;/del&gt; шуток.&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-463-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-463-1.jpg"/></item><item><title>Знаете как это бывает, начинаешь делать задачу, посидел, придумал архитектуру, реализовал, и тут…</title><link>https://cherkashin.dev/posts/462/</link><guid isPermaLink="true">https://cherkashin.dev/posts/462/</guid><description>Знаете как это бывает, начинаешь делать задачу, посидел, придумал архитектуру, реализовал, и тут начинается самое интересное... В одном месте что-то не учёл, в коде соседнего модуля вылез косяк, а время идёт, сроки горят и приходится подставить костыли и надеяться что когда-то можно будет это исправить. Да и переписыва...</description><pubDate>Mon, 30 Mar 2026 09:03:01 GMT</pubDate><content:encoded>&lt;p&gt;Знаете как это бывает, начинаешь делать задачу, посидел, придумал архитектуру, реализовал, и тут начинается самое интересное… В одном месте что-то не учёл, в коде соседнего модуля вылез косяк, а время идёт, сроки горят и приходится подставить костыли и надеяться что когда-то можно будет это исправить. Да и переписывать свой код больно, он же ваш, вы потратили на него время.&lt;/p&gt;
&lt;p&gt;Я это вот к чему. Астрологи объявили год агентного кодинга, все пишут как они ускоряются в 5-10 раз, но эта проблема никуда на самом деле не уходит.&lt;/p&gt;
&lt;p&gt;Вы ставите задачу кодексу, клоду или чем вы там пользуетесь, он реализует задачу, вы проверяете, а он архитектурно сделал что-то не так, какие-то требования не учёл, и вы начинаете просить агента исправить всё что он натворил в том же чате. И он делает примерно то же, что и мы - начинает либо фиксить баги, либо добавлять костыли. В итоге код уже не такой хороший, как если бы он сразу сделал нормально. А под конец агент ещё и начинает путаться, тупить и ходить вокруг да около.&lt;/p&gt;
&lt;p&gt;И тут на помощь приходит One Shot Prompting. Про подход я уже слышал, но по-настоящему понял его только на стриме Вани в &lt;a href=&quot;https://www.guidedao.xyz/&quot;&gt;GuideDAO&lt;/a&gt;. В общем, суть простая - вы не просите агента исправить все косяки. Вместо этого берёте исходный промпт и уточняете требования, чтобы избежать проблем, которые всплыли в первой реализации. И, конечно, без угрызений совести выкидываете первую версию.&lt;/p&gt;
&lt;p&gt;То есть по сути, теперь мы дешево можем делать почти сразу хорошо, переписать всё стало в разы проще.&lt;/p&gt;
&lt;p&gt;🧪 Пример из своего опыта. Я решил начать пилить небольшой пет-проект, который, надеюсь, когда-нибудь увидит свет. В проекте используется &lt;a href=&quot;https://maplibre.org/projects/gl-js&quot;&gt;MapLibre GL JS&lt;/a&gt; - библиотека для отображения векторных карт. После очередной фичи я решил попросить кодекс покрыть её playwright тестами, и тут началось.&lt;/p&gt;
&lt;p&gt;Он написал тесты и следующие полчаса пытался понять, почему же карта не отображается. Как джун, искал проблему методом тыка. Вносил изменения - карта не работает. Решил, что проблема в кеше - перезапускает дев-сервер. И так раз десять. В итоге он всё-таки дошёл до причины: WebGL, который используется в MapLibre, не работает, когда playwright запущен в headless режиме.&lt;/p&gt;
&lt;p&gt;С горем пополам тесты он написал, но на код, конечно, лучше не смотреть. Естественно, он не убрал все свои неудачные попытки пофиксить проблему.И это именно тот случай, когда нужен One Shot Prompting.&lt;/p&gt;
&lt;p&gt;Я просто спросил у кодекса, в чём была проблема, добавил это в исходный промпт, откатил изменения и запустил всё заново. В этот раз реализация прошла быстро, и код получился заметно чище.&lt;/p&gt;
&lt;p&gt;На работе теперь тоже постоянно применяю этот подход. После этого у меня даже появилась небольшая надежда, что сеньоров заменят не скоро. Потому что джунам гораздо сложнее делать ревью кода, который написал агент, а в итоге это легко может привести к неподдерживаемому коду. Но теперь за ними нужен глаз да глаз, чтобы не пропустить такой код в прод 😅.&lt;/p&gt;
&lt;p&gt;⚠️ У подхода, конечно, есть и минус. Токенов тратится больше. Поэтому если задача большая, а багов немного, иногда проще пойти на компромисс и просто попросить агента всё пофиксить.&lt;/p&gt;
&lt;p&gt;||А вообще теперь же с 1 марта нельзя говорить one shot prompting. Как это будет по-русски, «однократное задание по образцу»? 😆||&lt;/p&gt;
&lt;p&gt;А вы используете One Shot Prompting?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👍 — использую one shot prompting&lt;/li&gt;
&lt;li&gt;❤️ — правлю всё в одном чате&lt;/li&gt;
&lt;li&gt;😢 — почти не использую ИИ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-462-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-462-1.jpg"/></item><item><title>4 года назад я перешёл с винды на мак, подключил свой старый 2K монитор и вообще не понял прикола.</title><link>https://cherkashin.dev/posts/460/</link><guid isPermaLink="true">https://cherkashin.dev/posts/460/</guid><description>4 года назад я перешёл с винды на мак, подключил свой старый 2K монитор и вообще не понял прикола.

Монитор отлично работал с виндовым ноутом, но на маке всё поплыло.Текст мыльный, глаза уставали довольно быстро.

Я всё откладывал этот вопрос, а глаза продолжали страдать.

Наконец-то, взяв себя в руки, я пошёл в наш ку...</description><pubDate>Thu, 26 Mar 2026 08:39:44 GMT</pubDate><content:encoded>&lt;p&gt;4 года назад я перешёл с винды на мак, подключил свой старый 2K монитор и вообще не понял прикола.&lt;/p&gt;
&lt;p&gt;Монитор отлично работал с виндовым ноутом, но на маке всё поплыло.&lt;br&gt;
Текст мыльный, глаза уставали довольно быстро.&lt;/p&gt;
&lt;p&gt;Я всё откладывал этот вопрос, а глаза продолжали страдать.&lt;/p&gt;
&lt;p&gt;Наконец-то, взяв себя в руки, я пошёл в наш курский программистский чатик за советом. Умные люди рассказали про PPI у маков и посоветовали смотреть в одну из таких конфигураций:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;4K на 24 дюйма&lt;/li&gt;
&lt;li&gt;5K на 27 дюймов&lt;/li&gt;
&lt;li&gt;6K на 32 дюйма&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если очень грубо, PPI — это плотность пикселей на дюйм.&lt;/p&gt;
&lt;p&gt;Я решил взять 5K монитор и запустил исследование в ChatGPT, и он предложил мне 4 варианта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.citilink.ru/product/monitor-digma-pro-art-m-27-serebristyi-dm27sp02-1969304/&quot;&gt;27” Монитор DIGMA PRO Art M, 5120x2880&lt;/a&gt; — 54 990&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mvideo.ru/products/monitor-samsung-viewfinity-s9-s90pc-s27c902pai-27-ips-5120x2880-60gc-serebristyi-30069595&quot;&gt;Samsung ViewFinity S9 S90PC S27C902PAI 27” 5120x2880&lt;/a&gt; — 81 999&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mvideo.ru/products/monitor-digma-pro-dm27sp02-400580777&quot;&gt;Монитор Digma Pro DM27SP02&lt;/a&gt; — 84 906&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kuycon.ru/monitors/G27X%20SE/&quot;&gt;Kuycon G27X SE&lt;/a&gt; — от 80 000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я человек простой: что дешевле, то и беру.&lt;br&gt;
Поэтому остановился на Digma PRO.&lt;/p&gt;
&lt;p&gt;После 2К монитора, это просто сказка, смотреть одно удовольствие. Единственное неудобство — ножка не регулируется по высоте. Но сама по себе она более-менее высокая, так что с 14-дюймовым маком можно обойтись и без подставки.&lt;/p&gt;
&lt;p&gt;Пока ждал монитор нашел 2 способа улучшить качество на 2K мониторе:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;включить 2x масштабирование — тогда качество отличное, но всё огромное&lt;/li&gt;
&lt;li&gt;установить &lt;a href=&quot;https://github.com/waydabber/BetterDisplay&quot;&gt;BetterDisplay&lt;/a&gt; — специальную утилиту для мака для настройки монитора, и изображение становится чуть чётче, но всё ещё достаточно отстойное&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Кстати, обзоры этих мониторов можно посмотреть здесь:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=95K4t15yQz8&quot;&gt;Монитор для Mac за 50 тысяч — Digma 5k Pro Art M&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cQtmNOCq0A8&quot;&gt;Как выбрать монитор для Мака и MacOS? Потратил полмиллиона и узнал&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А как у вас дела&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👍 — обхожусь одним монитором&lt;/li&gt;
&lt;li&gt;😢 — тоже страдаю с внешним монитором&lt;/li&gt;
&lt;li&gt;🔥 — всё ок: монитор классный или на винде/линуксе таких проблем нет&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-460-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-460-1.jpg"/></item><item><title>Если честно, после того как я научился пользоваться гитом и разобрался, что такое git checkout, git…</title><link>https://cherkashin.dev/posts/459/</link><guid isPermaLink="true">https://cherkashin.dev/posts/459/</guid><description>Если честно, после того как я научился пользоваться гитом и разобрался, что такое git checkout, git branch, git merge, git commit, я не особо копал, какие ещё там есть команды. Конечно, использовал git rebase, reflog, reset, но не более того.

И вот только на прошлой неделе узнал, что такое git worktree. Пока ещё сам н...</description><pubDate>Mon, 23 Mar 2026 08:35:09 GMT</pubDate><content:encoded>&lt;p&gt;Если честно, после того как я научился пользоваться гитом и разобрался, что такое &lt;code&gt;git checkout&lt;/code&gt;, &lt;code&gt;git branch&lt;/code&gt;, &lt;code&gt;git merge&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt;, я не особо копал, какие ещё там есть команды. Конечно, использовал &lt;code&gt;git rebase&lt;/code&gt;, &lt;code&gt;reflog&lt;/code&gt;, &lt;code&gt;reset&lt;/code&gt;, но не более того.&lt;/p&gt;
&lt;p&gt;И вот только на прошлой неделе узнал, что такое &lt;code&gt;git worktree&lt;/code&gt;. Пока ещё сам не распробовал, но уже собираюсь заменить свой дополнительный клон рабочего репозитория на &lt;code&gt;worktree&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Часто бывает, что нужно параллельно ковырять две ветки: в одной делать задачу, в другой срочно что-то поправить. Или быстро переключиться в ветку для ревью. Или просто посмотреть старую версию, не трогая текущее состояние.&lt;/p&gt;
&lt;p&gt;У меня и сейчас для этого два отдельных &lt;code&gt;git clone&lt;/code&gt; одного и того же репозитория. Работает, конечно, но &lt;code&gt;clone&lt;/code&gt; — это всё-таки отдельный репозиторий со своим &lt;code&gt;.git&lt;/code&gt;. То есть папок у тебя будет столько же, сколько и с &lt;code&gt;worktree&lt;/code&gt;, но в случае с &lt;code&gt;clone&lt;/code&gt; ещё и история с git-объектами дублируется. У меня, например, один &lt;code&gt;.git&lt;/code&gt; весит около 4 ГБ…&lt;/p&gt;
&lt;p&gt;А &lt;code&gt;git worktree&lt;/code&gt; — это по сути несколько рабочих папок для одного репозитория. История и git-объекты при этом общие, а в дополнительной папке &lt;code&gt;.git&lt;/code&gt; — это не отдельная директория, а файл-ссылка на служебные данные основного репозитория.&lt;/p&gt;
&lt;p&gt;То есть разница такая:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git clone&lt;/code&gt; — отдельный репозиторий, отдельный &lt;code&gt;.git&lt;/code&gt;, отдельная история на диске.
&lt;code&gt;git worktree&lt;/code&gt; — ещё одна рабочая папка, но репозиторий под капотом общий.&lt;/p&gt;
&lt;p&gt;Создаётся всё буквально одной командой:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; ../project-review&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Если нужна новая ветка под задачу:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; -b&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; feature/button-fix&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; ../project-button-fix&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Дальше просто открываешь обе папки в IDE и спокойно работаешь параллельно.&lt;/p&gt;
&lt;p&gt;Посмотреть все &lt;code&gt;worktree&lt;/code&gt; можно так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Удалить так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; remove&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; ../project-review&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Подробнее можете &lt;a href=&quot;https://habr.com/ru/articles/826260/&quot;&gt;почитать в статье&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Узнал я об этой фиче, кстати, из Codex. Там есть специальная функция, чтобы быстро создать дополнительный &lt;code&gt;worktree&lt;/code&gt; и работать над несколькими задачами параллельно.&lt;/p&gt;
&lt;p&gt;👍 — если уже пользуетесь &lt;code&gt;worktree&lt;/code&gt;
🔥 — если, как и я, держите несколько клонов одного репо
🤔 — если вам вообще нет надобности держать несколько копий одного репозитория&lt;/p&gt;
&lt;p&gt;#git&lt;/p&gt;</content:encoded></item><item><title>Я искренне завидую людям, которые выступают на митапах и записывают курсы по программированию. Для…</title><link>https://cherkashin.dev/posts/458/</link><guid isPermaLink="true">https://cherkashin.dev/posts/458/</guid><description>Я искренне завидую людям, которые выступают на митапах и записывают курсы по программированию. Для меня это кажется чем-то невероятно сложным, поэтому я не выхожу за пределы ведения каналов 😅

Сегодня хочу порекомендовать канал моего тёзки Саши - Frontend вдохновляет.

У нас с ним есть что-то общее: мы оба фронтендеры...</description><pubDate>Wed, 18 Mar 2026 09:28:01 GMT</pubDate><content:encoded>&lt;p&gt;Я искренне завидую людям, которые выступают на митапах и записывают курсы по программированию. Для меня это кажется чем-то невероятно сложным, поэтому я не выхожу за пределы ведения каналов 😅&lt;/p&gt;
&lt;p&gt;Сегодня хочу порекомендовать канал моего тёзки Саши - &lt;a href=&quot;https://t.me/front_everyday&quot;&gt;Frontend вдохновляет&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;У нас с ним есть что-то общее: мы оба фронтендеры и оба используем Obsidian. А у себя в канале Саша делится полезным из практики, заметками про инструменты и просто интересными наблюдениями.&lt;/p&gt;
&lt;p&gt;Что у него посмотреть:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/front_everyday/1264&quot;&gt;Для ценителей Vue: песочница с подводными камнями реактивности&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/front_everyday/1257&quot;&gt;Про Obsidian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/front_everyday/1254&quot;&gt;Про динамичные ключи в i18n&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/front_everyday/1226&quot;&gt;Про выступления на митапах&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/front_everyday/1225&quot;&gt;Про опыт с ИИ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/front_everyday/1191&quot;&gt;Про мошеннические действия под прикрытием рекрутеров&lt;/a&gt; — мой любимый 😅&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/front_everyday/1189&quot;&gt;Figma Make. Что это и как работает&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Плюс у Саши есть &lt;a href=&quot;https://stepik.org/course/236544&quot;&gt;курс на Stepik&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;А ещё он делится прочитанной художественной литературой и пройденными играми.&lt;/p&gt;
&lt;p&gt;В общем, рекомендую заглянуть в канал&lt;/p&gt;
&lt;p&gt;👉  &lt;a href=&quot;https://t.me/front_everyday&quot;&gt;https://t.me/front_everyday&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#рекомендую_канал&lt;/p&gt;</content:encoded></item><item><title>Недавно фиксил баг у себя в блоге, и заодно нужно было покрыть тестами парсер тегов для…</title><link>https://cherkashin.dev/posts/457/</link><guid isPermaLink="true">https://cherkashin.dev/posts/457/</guid><description>Недавно фиксил баг у себя в блоге, и заодно нужно было покрыть тестами парсер тегов для телеграм-постов.

В какой-то момент вспомнил, что в Node.js уже есть встроенный тест-раннер. Решил не тащить лишние зависимости и просто проверить, насколько он вообще живой.

В итоге оказалось, что для таких задач — более чем ок.

...</description><pubDate>Mon, 16 Mar 2026 09:51:02 GMT</pubDate><content:encoded>&lt;p&gt;Недавно фиксил баг у себя в блоге, и заодно нужно было покрыть тестами парсер тегов для телеграм-постов.&lt;/p&gt;
&lt;p&gt;В какой-то момент вспомнил, что в Node.js уже есть встроенный тест-раннер. Решил не тащить лишние зависимости и просто проверить, насколько он вообще живой.&lt;/p&gt;
&lt;p&gt;В итоге оказалось, что для таких задач — более чем ок.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/acherkashin/acherkashin.github.io/blob/main/tests/telegram-tags.util.test.ts&quot;&gt;https://github.com/acherkashin/acherkashin.github.io/blob/main/tests/telegram-tags.util.test.ts&lt;/a&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; assert &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;node:assert/strict&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; test &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;node:test&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;extracts multiple hashtags from a single line&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; tags&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; extractTelegramTagsFromMarkdown&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;#frontend #testing #astro&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  assert.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;deepEqual&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(tags, [&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;frontend&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;testing&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;astro&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Что ещё приятно — тесты можно писать на чистом TypeScript без установки дополнительных пакетов.&lt;/p&gt;
&lt;p&gt;Для утилит, парсеров, серверного кода и прочих небольших юнит-тестов этого раннера вполне хватает.&lt;/p&gt;
&lt;p&gt;Но если у вас фронтенд-проект и нужны тесты компонентов, браузерное окружение, снапшоты, расширенные матчеры и привычная экосистема вокруг раннера, то Jest или Vitest тут ощущаются заметно сильнее.&lt;/p&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nodejs.org/api/test.html&quot;&gt;Документация&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://glebbahmutov.com/blog/trying-node-test-runner/&quot;&gt;Trying Node.js Test Runner&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А вы чем гоняете тесты?&lt;/p&gt;
&lt;p&gt;🔥 — Vitest&lt;br&gt;
👍 — Jest
❤️ — Что-то другое (напишу в комментариях)&lt;/p&gt;
&lt;p&gt;#nodejs #tests&lt;/p&gt;</content:encoded></item><item><title>Я занимаюсь фронтенд-разработкой около 9 лет, но, к своему стыду, ни разу не «игрался со шрифтами».…</title><link>https://cherkashin.dev/posts/456/</link><guid isPermaLink="true">https://cherkashin.dev/posts/456/</guid><description>Я занимаюсь фронтенд-разработкой около 9 лет, но, к своему стыду, ни разу не «игрался со шрифтами». Во всех проектах, над которыми я работал, был либо подключён какой-то шрифт из Google Fonts, либо всё уже было настроено, либо использовался просто какой-то дефолтный шрифт из шаблона.

Но вот шрифты всё-таки меня настиг...</description><pubDate>Fri, 13 Mar 2026 08:57:35 GMT</pubDate><content:encoded>&lt;p&gt;Я занимаюсь фронтенд-разработкой около 9 лет, но, к своему стыду, ни разу не «игрался со шрифтами». Во всех проектах, над которыми я работал, был либо подключён какой-то шрифт из Google Fonts, либо всё уже было настроено, либо использовался просто какой-то дефолтный шрифт из шаблона.&lt;/p&gt;
&lt;p&gt;Но вот шрифты всё-таки меня настигли. Во время редизайна дизайнер решил, что Nunito уже не модно, и предложил перейти на Inter. Когда мы обновили шрифт, наш интерфейс разнесло во все стороны 😅 Inter оказался заметно больше.&lt;/p&gt;
&lt;p&gt;Сначала мы решили пойти самым простым путём: поменять значения наших дизайн-токенов и сделать их на 1px меньше, чтобы компенсировать переход на новый шрифт. Но это не сработало: наш конструктор позволяет указывать кастомные шрифты, поэтому такой вариант отпал.&lt;/p&gt;
&lt;p&gt;И вот после очередного сеанса &lt;del&gt;гугления&lt;/del&gt; промптинга ChatGPT подсказал мне, что есть такое свойство, как &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@font-face/size-adjust&quot;&gt;size-adjust&lt;/a&gt;, которое позволяет уменьшить весь шрифт. Размеры и отступы всё равно, конечно, немного отличаются, но так можно избежать изменения дизайн-токенов.&lt;/p&gt;
&lt;p&gt;Для наглядности это выглядит примерно так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;@font-face&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  font-family&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: Inter;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  font-style&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;normal&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  font-weight&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 900&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  font-display&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;swap&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  size-adjust&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;93&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  src&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfMZg.ttf&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;truetype&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;А ещё я собрал &lt;a href=&quot;http://cherkashin.dev/demos/size-adjust-playground/index.html&quot;&gt;небольшую демку&lt;/a&gt;, где можно поиграться с этим свойством.&lt;/p&gt;
&lt;p&gt;👍 — если знали про size-adjust
❤️ — если узнали что-то новое&lt;/p&gt;
&lt;p&gt;#css&lt;/p&gt;</content:encoded></item><item><title>Если всё горит — поговори 🔥</title><link>https://cherkashin.dev/posts/455/</link><guid isPermaLink="true">https://cherkashin.dev/posts/455/</guid><description>Если всё горит — поговори 🔥

Это была уже третья неделя подряд, когда у меня в понедельник выходной. Да-да, на прошлой неделе я вообще прогулял — прям как в школе.

Дел как-то навалилось много: и на работе, и личных. И перед запоздалым началом новой рабочей недели хочется лишний раз напомнить — в первую очередь себе —...</description><pubDate>Tue, 10 Mar 2026 11:13:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Если всё горит — поговори 🔥&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Это была уже третья неделя подряд, когда у меня в понедельник выходной. Да-да, на прошлой неделе я вообще прогулял — прям как в школе.&lt;/p&gt;
&lt;p&gt;Дел как-то навалилось много: и на работе, и личных. И перед запоздалым началом новой рабочей недели хочется лишний раз напомнить — в первую очередь себе — простую вещь:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;если всё горит — поговори.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;У меня уже который раз происходит одна и та же фигня. Работы вагон и маленькая тележка: ничего не успеваешь, бежишь изо всех сил, нервничаешь, постоянно раздражаешься. Бесит всё так, что аж пот по спине течёт.&lt;/p&gt;
&lt;p&gt;А потом оказывается, что иногда достаточно просто поговорить.&lt;/p&gt;
&lt;p&gt;Только за прошлую неделю у меня было две такие ситуации:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Пошёл проводить 1:1 с коллегой. В итоге сам отвлёкся, проговорили разные вещи — и внезапно уже не кажется, что проблемы такие большие.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Обсудил текущую проблему по проекту с коллегой. Он посмотрел на неё со стороны и предложил решение, о котором я вообще не думал. В итоге снова оказалось, что я просто больше загонялся.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Иногда мы настолько погружаемся в проблему, что начинаем вариться в собственных мыслях. А разговор иногда просто помогает немного проветрить голову.&lt;/p&gt;
&lt;p&gt;Правда, есть нюанс.&lt;br&gt;
Если кто-то в такой момент захочет поговорить со мной &lt;strong&gt;«ни о чём»&lt;/strong&gt;, у меня может полыхнуть ещё сильнее 😅.&lt;/p&gt;
&lt;p&gt;В общем, хорошей недели всем 👋 .
Ставь ❤️, чтобы эта неделя прошла без происшествий.&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-455-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-455-1.jpg"/></item><item><title>Девушки, с 8 марта 🌷</title><link>https://cherkashin.dev/posts/453/</link><guid isPermaLink="true">https://cherkashin.dev/posts/453/</guid><description>Девушки, с 8 марта 🌷

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

А от меня небольшой виртуальный букет — тюльпаны, выращенные на чистом CSS:

https://codepen.io/cherkalexander/pen/EagyGZw</description><pubDate>Sun, 08 Mar 2026 08:41:22 GMT</pubDate><content:encoded>&lt;p&gt;Девушки, с 8 марта 🌷&lt;/p&gt;
&lt;p&gt;Пусть в жизни всё получается, планы исполняются, а рядом всегда будут люди, которые поддерживают и вдохновляют.&lt;/p&gt;
&lt;p&gt;А от меня небольшой виртуальный букет — тюльпаны, выращенные на чистом CSS:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://codepen.io/cherkalexander/pen/EagyGZw&quot;&gt;https://codepen.io/cherkalexander/pen/EagyGZw&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-453-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-453-1.jpg"/></item><item><title>Пока ремонт особо не напрягает, появилось время вернуться к рутине. Начал смотреть стримы про…</title><link>https://cherkashin.dev/posts/452/</link><guid isPermaLink="true">https://cherkashin.dev/posts/452/</guid><description>Пока ремонт особо не напрягает, появилось время вернуться к рутине. Начал смотреть стримы про вайбкодинг в Guide DAO, где сейчас прохожу обучение. Стримы проходят раз в неделю, где ребята продолжают развивать один и тот же проект — шаг за шагом углубляются в архитектуру и работу с агентами.

В этот раз для себя наконец...</description><pubDate>Thu, 05 Mar 2026 10:00:27 GMT</pubDate><content:encoded>&lt;p&gt;Пока ремонт особо не напрягает, появилось время вернуться к рутине. Начал смотреть стримы про вайбкодинг в Guide DAO, где сейчас прохожу обучение. Стримы проходят раз в неделю, где ребята продолжают развивать один и тот же проект — шаг за шагом углубляются в архитектуру и работу с агентами.&lt;/p&gt;
&lt;p&gt;В этот раз для себя наконец нормально понял тему скиллов.
&lt;strong&gt;Skills — это по сути «ленивые» инструкции&lt;/strong&gt;: они загружаются в промпт только тогда, когда действительно нужны.&lt;/p&gt;
&lt;p&gt;Рано или поздно агент начинает делать что-то «не по-нашему». Например, пишет e2e-тесты без структуры, игнорирует page object или общие хелперы.&lt;/p&gt;
&lt;p&gt;Первая реакция — добавить правила в &amp;#x3C;CLAUDE.md&gt;:
— использовать Playwright
— придерживаться page object
— выносить повторяющуюся логику
— аккуратно работать с асинхронностью&lt;/p&gt;
&lt;p&gt;Это работает. Но файл быстро разрастается, если напрямую в нём описывать все правила для тестов, API, миграций, логирования и т.д.. В итоге системный промпт перегружен, хотя для конкретной задачи нужна лишь часть правил. Зачем тянуть всё сразу?&lt;/p&gt;
&lt;p&gt;Вот здесь и нужны skills.&lt;/p&gt;
&lt;p&gt;Скилл — это заголовок (когда применять) и тело (инструкции). Агент всегда видит только заголовки, а детали подтягивает по необходимости.
Задача на e2e — активировался нужный скилл. Пишем что-то другое — скилл не подгружаем, чтобы не засорять контекст ненужными деталями.&lt;/p&gt;
&lt;p&gt;К слову, на следующей неделе в &lt;a href=&quot;https://www.guidedao.xyz/jtbd&quot;&gt;Guide DAO стартует живой поток по вайбкодингу&lt;/a&gt;: формат стримов, небольшие группы, практика с домашками и обратной связью, длительность около полутора–двух месяцев. После покупки участники получают доступ ко всей платформе Guide DAO — стримам, курсам и комьюнити. Сейчас по промокоду 🏷 &lt;code&gt;CHERKASHIN&lt;/code&gt; действует скидка 30% (плюс около 10% на сайте).&lt;/p&gt;
&lt;p&gt;Из других полезных вещей, которые разбирали на стримах:&lt;/p&gt;
&lt;p&gt;• &lt;a href=&quot;https://modelcontextprotocol.io/&quot;&gt;MCP-серверы&lt;/a&gt; — позволяют агенту выходить во внешний мир: сходить в Jira, базу данных или API и собрать данные.
• &lt;a href=&quot;https://code.claude.com/docs/en/commands&quot;&gt;Команды&lt;/a&gt; — кастомные slash-команды с заранее заданным сценарием или промптом для повторяющихся действий.
• &lt;a href=&quot;https://code.claude.com/docs/en/hooks&quot;&gt;Хуки&lt;/a&gt; — точки расширения, которые позволяют выполнить код в определённые моменты работы агента (например, после генерации плана).
• &lt;a href=&quot;https://github.com/github/spec-kit&quot;&gt;spec-kit&lt;/a&gt; — spec-kit помогает быстро получить черновик спецификации проекта, который потом можно отревьюить и доработать.&lt;/p&gt;
&lt;p&gt;И в конце стрима зацепила одна мысль 💡. Парни обсуждали, что нам, по сути, повезло войти в ИТ ещё до появления ИИ и агентов. Мы успели набить базовые знания и привыкли разбираться в проблемах самостоятельно. Сейчас это объективно сложнее: когда ИИ может написать решение в разы быстрее, нужна большая сила воли, чтобы не просто «попросить агента», а действительно вникнуть, разобраться и чему-то научиться. Заставить себя изучать новое в такой реальности — отдельный навык.&lt;/p&gt;
&lt;p&gt;Кстати, ребята выложили в открытый доступ 👉 &lt;a href=&quot;https://www.youtube.com/watch?v=w610UPcMeIg&quot;&gt;&lt;u&gt;один из стримов по вайбкодингу&lt;/u&gt;&lt;/a&gt;, где на практике разбирается как использовать spec-kit.&lt;/p&gt;
&lt;p&gt;Ставьте:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔥 — если чувствуете себя уверенно в вайбкодинге&lt;/li&gt;
&lt;li&gt;👍 — если пока наблюдаете со стороны&lt;/li&gt;
&lt;li&gt;😱 — если всё сильнее переживаете, что ИИ вас заменит&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-452-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-452-1.jpg"/></item><item><title>Как-то я немного забегался: «Я 💛 Фронтенд» прошёл уже две недели назад, а я только сейчас нашёл…</title><link>https://cherkashin.dev/posts/442/</link><guid isPermaLink="true">https://cherkashin.dev/posts/442/</guid><description>Как-то я немного забегался: «Я 💛 Фронтенд» прошёл уже две недели назад, а я только сейчас нашёл время сесть и подвести итоги 🙂

Это уже третий раз, когда я был на конференции в офлайне, и — что символично — третья новая локация. В Москве я обычно езжу только на метро, но в этот раз пришлось пересесть на автобус, чтоб...</description><pubDate>Mon, 02 Mar 2026 09:05:07 GMT</pubDate><content:encoded>&lt;p&gt;Как-то я немного забегался: &lt;strong&gt;«Я 💛 Фронтенд»&lt;/strong&gt; прошёл уже две недели назад, а я только сейчас нашёл время сесть и подвести итоги 🙂&lt;/p&gt;
&lt;p&gt;Это уже третий раз, когда я был на конференции в офлайне, и — что символично — третья новая локация. В Москве я обычно езжу только на метро, но в этот раз пришлось пересесть на автобус, чтобы добраться до Мосфильма, где и проходила конференция 🎬&lt;/p&gt;
&lt;p&gt;В отличие от предыдущих разов, это была первая конференция, на которой я всё-таки поборол интроверта внутри себя и походил по активностям.&lt;/p&gt;
&lt;p&gt;Ещё до начала докладов я успел:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;🧙‍♂️ побороться с колдуном на платформе Source Craft — это такой аналог GitHub от Яндекса;

👔 побыть CEO в симуляторе и решить, что важнее: устранить технический долг или запилить новую фичу;

🎲 а позже поиграть в Alias для фронтендеров.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Короче, без фирменных носков и шоппера я, конечно, не уехал 😄&lt;/p&gt;
&lt;p&gt;На 14 февраля всё-таки удалось попасть в кино — правда, вместо фильма там были доклады. Вот мой топ-3:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Fpx_lpxuMhY&quot;&gt;По-настоящему адаптивный интерфейс.&lt;/a&gt; Рома рассказал, что адаптивность — это уже давно не только брейкпоинты. Сейчас мы мыслим компонентами, а современные браузеры поддерживают кучу новых возможностей, чтобы делать их адаптивными. Посмотрите хотя бы на &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/clamp&quot;&gt;clamp&lt;/a&gt;() и &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Containment/Container_size_and_style_queries&quot;&gt;style queries.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=F0Yl1l3JB8A&quot;&gt;Локальные модели: как запустить ИИ в браузере.&lt;/a&gt; Очень интересный доклад о том, как голосовой ввод и LLM в браузере могут сделать UX ещё лучше.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=nBbTeDUYgyU&quot;&gt;Что на самом деле важно в разработке?.&lt;/a&gt; Каждый раз убеждаюсь, что самые интересные доклады — не технические. Спасибо Владимиру за напоминание о том, что действительно важно ❤️&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Но, как &lt;a href=&quot;https://t.me/cherkashindev/396&quot;&gt;я уже говорил,&lt;/a&gt; конференции — это не только про доклады. Это про живое общение с живыми людьми, а не где-то в чатах или онлайне, где мы и так проводим слишком много времени.&lt;/p&gt;
&lt;p&gt;Я приехал со списком вопросов, на которые хотел получить ответы. И, проходя в очередной раз мимо столиков, неожиданно увидел &lt;a href=&quot;http://t.me/frontend_lead_mentor&quot;&gt;Женю Черкасова.&lt;/a&gt; Мы разговорились: у кого как выстроены процессы, сколько длится релизный цикл, сколько времени занимает регресс… В какой-то момент я понял, что мы уже пропустили следующий доклад 😅&lt;/p&gt;
&lt;p&gt;А ещё на конференции есть секция «Кофе с Talk’ом» ☕️ — там за чашкой кофе можно задать любые вопросы. Мне кажется, ребята меня уже запомнили: я каждый год пристаю к ним с расспросами. Так как я стал тимлидом, в этот раз больше всего интересовался коммуникацией с продактом и релизным циклом.&lt;/p&gt;
&lt;p&gt;В общем, конференция, как всегда, была на высоте 🔥. Я уехал с ответами на часть волнующих меня вопросов и с кучей новых идей.&lt;/p&gt;
&lt;p&gt;И отдельное спасибо моей любимой жене за то, что отпустила меня, несмотря на то, что это было 14 февраля 💛.&lt;/p&gt;
&lt;p&gt;#conference&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-442-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-442-1.jpg"/></item><item><title>Мы тут недавно в компании разбирались, как мы используем ИИ и где ещё можно его интегрировать. В…</title><link>https://cherkashin.dev/posts/440/</link><guid isPermaLink="true">https://cherkashin.dev/posts/440/</guid><description>Мы тут недавно в компании разбирались, как мы используем ИИ и где ещё можно его интегрировать. В процессе разговор зашёл о код-ревью.Мы используем self-hosted Gitea, а это значит, что никакого встроенного ИИ-код-ревью у нас, увы, нет.

Поэтому вчера утром я открыл Cline, вооружился Claude и, потратив все деньги $4 и пр...</description><pubDate>Fri, 27 Feb 2026 10:08:27 GMT</pubDate><content:encoded>&lt;p&gt;Мы тут недавно в компании разбирались, как мы используем ИИ и где ещё можно его интегрировать. В процессе разговор зашёл о код-ревью.&lt;br&gt;
Мы используем self-hosted Gitea, а это значит, что никакого встроенного ИИ-код-ревью у нас, увы, нет.&lt;/p&gt;
&lt;p&gt;Поэтому вчера утром я открыл Cline, вооружился Claude и, потратив &lt;del&gt;все деньги&lt;/del&gt; $4 и примерно час времени, навайбкодил пример сетапа с docker-compose файлом, Gitea и &lt;a href=&quot;https://qodo-merge-docs.qodo.ai/installation/gitea/&quot;&gt;PR Agent.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Claude сам провёл анализ и выбрал PR Agent, а затем написал подробную пошаговую инструкцию по интеграции с Gitea через вебхуки. В итоге уже через час всё было готово, и мне оставалось только попросить ChatGPT написать плохой код — чтобы проверить, как вообще будет выглядеть код-ревью от ИИ.&lt;/p&gt;
&lt;p&gt;Вроде выглядит сносно, но нужно проверять, как он будет работать на реальной кодовой базе.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/acherkashin/gitea-review-example&quot;&gt;Репозиторий здесь.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Расскажите, а вы используете ИИ для код-ревью?&lt;br&gt;
Ставьте:&lt;br&gt;
👍 — если да и вам зашло&lt;br&gt;
😢 — если пробовали, но не прижилось&lt;br&gt;
😱 — если у вас код-ревью это “заапрувь по братски”&lt;/p&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-440-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-440-1.jpg"/></item><item><title>Самой большой проблемой при миграции с 🇯🇵Notion на 💎 Obsidian были базы данных</title><link>https://cherkashin.dev/posts/437/</link><guid isPermaLink="true">https://cherkashin.dev/posts/437/</guid><description>Самой большой проблемой при миграции с 🇯🇵Notion на 💎 Obsidian были базы данных

В Obsidian попросту не было их полной альтернативы, поэтому пришлось пере-придумать свой подход к ведению проектов с помощью плагинов dataview и tasks.

Суть обоих плагинов проста — они позволяют писать запросы с помощью специального син...</description><pubDate>Tue, 24 Feb 2026 09:07:01 GMT</pubDate><content:encoded>&lt;p&gt;Самой большой проблемой при миграции с 🇯🇵Notion на 💎 Obsidian были базы данных&lt;/p&gt;
&lt;p&gt;В Obsidian попросту не было их полной альтернативы, поэтому &lt;a href=&quot;https://t.me/cherkashindev/231&quot;&gt;пришлось пере-придумать свой подход&lt;/a&gt; к ведению проектов с помощью плагинов &lt;a href=&quot;https://github.com/blacksmithgu/obsidian-dataview&quot;&gt;dataview&lt;/a&gt; и &lt;a href=&quot;https://github.com/obsidian-tasks-group/obsidian-tasks&quot;&gt;tasks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Суть обоих плагинов проста — они позволяют писать запросы с помощью специального синтаксиса к заметкам и задачам и выводить результаты на странице.&lt;/p&gt;
&lt;p&gt;Я как-то это упустил, но в прошлом году появился новый встроенный &lt;a href=&quot;https://help.obsidian.md/bases&quot;&gt;плагин Bases&lt;/a&gt;, который как раз и представляет собой альтернативу тем самым базам в Notion.&lt;/p&gt;
&lt;p&gt;Однако по своей сути он скорее похож на dataview — это просто ещё один язык запросов к заметкам, который использует YAML синтаксис.&lt;/p&gt;
&lt;p&gt;Вот, например, так выглядит конфигурация представления с постами для блога, которые сейчас в работе 👇&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
filters:
  and:
    - file.ext == &quot;md&quot;
    - file.path.startsWith(&quot;2.Areas/A.Блог/Посты&quot;)
views:
  - type: table
    name: In Progress
    filters:
      or:
        - file.path.startsWith(&quot;2.Areas/A.Блог/Посты/2.InProgress&quot;)
        - status.contains(&quot;➡️ In Progress&quot;)
    order:
      - file.name
      - status
      - tags
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Именно это и содержится в файлах с расширением .base.&lt;/p&gt;
&lt;p&gt;🧩 &lt;strong&gt;В Notion и Obsidian, есть одно принципиальное различие, при настройке баз данных.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В Notion мы создаём отдельную базу данных, которая хранит записи определённого типа, а затем с помощью фильтров можем показывать только часть этих записей.&lt;/p&gt;
&lt;p&gt;Например, если мы строим трекер задач в Notion, у нас будет две базы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Задачи&lt;/li&gt;
&lt;li&gt;Проекты
&lt;ul&gt;
&lt;li&gt;А на странице проекта мы можем добавить представление, где отображаются только задачи этого проекта.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В Obsidian всё иначе.&lt;/p&gt;
&lt;p&gt;У нас есть одна «главная база данных» — все наши заметки. Каждая запись — это обычная текстовая заметка. У заметок нет как такового типа.&lt;/p&gt;
&lt;p&gt;Поэтому, чтобы отличить задачи от проектов, мы будем фильтровать их либо по пути заметки, либо по тегу.&lt;/p&gt;
&lt;p&gt;Я бы сказал, что это всё же преимущество Notion — там можно гибко совмещать содержимое разных баз в одном представлении. Например, легко создать представление «Заметки, созданные на прошлой неделе».&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;⚙️ Что умеет?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Поддерживается 4 типа представлений:
&lt;ul&gt;
&lt;li&gt;таблица&lt;/li&gt;
&lt;li&gt;список&lt;/li&gt;
&lt;li&gt;карточки&lt;/li&gt;
&lt;li&gt;карта (если установить &lt;a href=&quot;https://help.obsidian.md/bases/views/map&quot;&gt;дополнительный плагин&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Поддерживает inline-базы данных — почти как в Notion&lt;/li&gt;
&lt;li&gt;Работают формулы и фильтры&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;❌ Недостатки&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Нет представления канбан-доски. Это, пожалуй, самое печальное. Надеюсь, со временем добавят.&lt;/li&gt;
&lt;li&gt;Не получится нормально использовать создание новой заметки прямо из базы через кнопку “+ New”, потому что:
&lt;ul&gt;
&lt;li&gt;все заметки создаются в дефолтной папке — из-за этого не срабатывает &lt;a href=&quot;https://github.com/SilentVoid13/Templater&quot;&gt;шаблон&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;в созданной заметке появляются только те поля, которые сконфигурированы в базе; поля из шаблона не подтягиваются&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Подробнее, можно посмотреть тут:
• &lt;a href=&quot;https://youtu.be/c2gd7fDbNOc?list=TLPQMTkwMjIwMjbJFVCZWUcCSQ&amp;#x26;t=1093&quot;&gt;Умные таблицы в Obsidian. Плагины Bases и DataView. Пошаговая инструкция.&lt;/a&gt;
• &lt;a href=&quot;https://www.youtube.com/watch?v=rGwDQzA4HzA&quot;&gt;Умные таблицы в Obsidian. Дополнения к первой части. Вставка в тело страницы. Настройка и синтаксис.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#obsidian&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-437-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-437-1.jpg"/></item><item><title>Выходные закончились, а отдохнуть, как всегда, не получилось. Работать не хочется… но надо 😅.</title><link>https://cherkashin.dev/posts/436/</link><guid isPermaLink="true">https://cherkashin.dev/posts/436/</guid><description>Выходные закончились, а отдохнуть, как всегда, не получилось. Работать не хочется… но надо 😅.

Принёс вам альбом с музыкой под стать понедельнику — с говорящим названием Заебудни. Тут даже объяснять ничего не нужно. Каждая песня — бриллиант 💎.

Мои любимые:
• Зачем тебе отпуск?
• Можешь хуже

В общем, хорошей рабочей...</description><pubDate>Mon, 16 Feb 2026 07:53:01 GMT</pubDate><content:encoded>&lt;p&gt;Выходные закончились, а отдохнуть, как всегда, не получилось. Работать не хочется… но надо 😅.&lt;/p&gt;
&lt;p&gt;Принёс вам альбом с музыкой под стать понедельнику — с говорящим названием &lt;a href=&quot;https://music.yandex.ru/album/39924596&quot;&gt;Заебудни&lt;/a&gt;. Тут даже объяснять ничего не нужно. Каждая песня — бриллиант 💎.&lt;/p&gt;
&lt;p&gt;Мои любимые:
• &lt;a href=&quot;https://music.yandex.ru/album/39924596/track/146589964&quot;&gt;Зачем тебе отпуск?&lt;/a&gt;
• &lt;a href=&quot;https://music.yandex.ru/album/39924596/track/146589970&quot;&gt;Можешь хуже&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;В общем, хорошей рабочей недели 👍 Пусть она пройдёт легче, чем началась.
А вы работаете под музыку? Если да — под какую? 🎧&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔥 — часто работаю под музыку&lt;/li&gt;
&lt;li&gt;👍 — включаю музыку, когда делаю задачи, где всё понятно&lt;/li&gt;
&lt;li&gt;❤️ — не работаю под музыку&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-436-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-436-1.jpg"/></item><item><title>Как научить машину понимать смысл слов</title><link>https://cherkashin.dev/posts/433/</link><guid isPermaLink="true">https://cherkashin.dev/posts/433/</guid><description>Как научить машину понимать смысл слов

Я думаю все вы слышали про векторные базы данных. В прошлом посте обещал поделиться статьёй про то, как же слова и целые тексты превращаются в вектора.

«Привет! Я [0.44, -0.91, 0.66...]» или как научить машину понимать смысл слов

В машинном обучении есть базовое правило: модель...</description><pubDate>Thu, 12 Feb 2026 08:03:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Как научить машину понимать смысл слов&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я думаю все вы слышали про векторные базы данных. В &lt;a href=&quot;https://t.me/cherkashindev/427&quot;&gt;прошлом посте&lt;/a&gt; обещал поделиться статьёй про то, как же слова и целые тексты превращаются в вектора.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/companies/ruvds/articles/983958/&quot;&gt;«Привет! Я [0.44, -0.91, 0.66…]» или как научить машину понимать смысл слов&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;В машинном обучении есть базовое правило: &lt;strong&gt;модель умеет работать только с числами&lt;/strong&gt;.&lt;br&gt;
Поэтому любой объект — текст, картинку, звук — сначала нужно превратить в числовое представление. Только тогда модель сможет понять, что «груша» связана с «яблоком» куда больше, чем с «теплоходом»&lt;/p&gt;
&lt;p&gt;Самый простой вариант для текста — 🔢 &lt;strong&gt;one hot encoding&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Мы берём словарь и каждому слову ставим в соответствие вектор, где одна позиция равна 1, а все остальные — 0.&lt;/p&gt;
&lt;p&gt;Возьмём предложения:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;The movie was good.&lt;/li&gt;
&lt;li&gt;The movie was bad.&lt;/li&gt;
&lt;li&gt;The movide was awesome.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Кодировка на первой картинке.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Формально задача решена, но есть проблема: такие векторы ничего не говорят о смысле слов.
Для модели слова «кот» и «собака» так же не похожи друг на друга, как «кот» и «кирпич».&lt;/p&gt;
&lt;p&gt;Плюс векторы получаются «разреженными» — огромными и почти полностью заполненными нулями. Ну и, конечно, это потребует большого количества ресурсов для обработки.&lt;/p&gt;
&lt;p&gt;👉 Следующий шаг — &lt;strong&gt;мешок слов и N-граммы&lt;/strong&gt;.&lt;br&gt;
Мы начинаем учитывать не отдельные слова, а их последовательности.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Кодировка на второй картинке&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Но N-граммы смотрят только на ограниченное число слов и строго по порядку. Поэтому они не улавливают более глубокие смысловые связи.&lt;/p&gt;
&lt;p&gt;В реальности таких возможных N-грамм — тысячи, и &lt;strong&gt;большая часть значений всегда равна 0&lt;/strong&gt;. То есть, проблема разреженных векторов полностью не уходит.&lt;/p&gt;
&lt;p&gt;Чтобы модель работала лучше, ей нужно понимать &lt;strong&gt;семантику&lt;/strong&gt; и &lt;strong&gt;контекст&lt;/strong&gt;.&lt;br&gt;
Здесь и появляются 🔡 &lt;strong&gt;word embeddings&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Эмбеддинг — это плотный числовой вектор фиксированной размерности, почти без нулей. Идея в том, что &lt;strong&gt;похожие по смыслу слова имеют похожие векторы&lt;/strong&gt;, а направление в векторном пространстве несёт смысл.&lt;/p&gt;
&lt;p&gt;В статье это объясняется на наглядном примере с животными.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сначала берётся одно измерение — &lt;strong&gt;размер&lt;/strong&gt;. Животные с похожими габаритами находятся рядом.&lt;/li&gt;
&lt;li&gt;Затем добавляется второе измерение — &lt;strong&gt;хищность&lt;/strong&gt;. В таком пространстве 🦁 «лев» и 🐯 «тигр» оказываются близко (крупные и опасные), 🐄 «корова» — отдельно (крупная, но безопасная), а 🐹 «хомяк» — совсем в другой области.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Когда слова представлены такими векторами, с ними можно выполнять математические операции:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;V(Madrid) + V(Germany) − V(Spain) ≈ V(Berlin)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;если мы возьмём слово «Мадрид», добавим «Германия» и вычтем «Испания», ближайшим полученным словом будет «Берлин». Это работает, потому что Мадрид — столица Испании. Когда мы убираем атрибуты, связанные с Испанией, и добавляем атрибуты, связанные с Германией, результирующий вектор тесно совпадает с Берлином, столицей Германии.&lt;/p&gt;
&lt;p&gt;Сами эмбеддинги генерируются с помощью специально обученных моделей.
Ну а про сам подход генерации лучше почитать &lt;a href=&quot;https://habr.com/ru/companies/ruvds/articles/983958/&quot;&gt;непосредственно в стать&lt;/a&gt;.  А на гифке можете посмотреть, как с помощью метода главных компонент визуализировать эмбеддинги.&lt;/p&gt;
&lt;p&gt;👍 — если работал с эмбеддингами
❤️ — если интересно, но пока не довелось
👀 — если не твоя тема&lt;/p&gt;
&lt;p&gt;#ai #fridayreading&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-433-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-433-1.jpg"/></item><item><title>За последние пару месяцев видел пару публикаций у знакомых про отказ от соц сетей или их осознанное…</title><link>https://cherkashin.dev/posts/429/</link><guid isPermaLink="true">https://cherkashin.dev/posts/429/</guid><description>За последние пару месяцев видел пару публикаций у знакомых про отказ от соц сетей или их осознанное ограничение. Я любитель поскролить ленту и насытиться лёгким дофамином, так что для меня тема более чем актуальная, поэтому я начал пользоваться One Sec.

❓ Что такое One Sec?

Это приложение, которое помогает ограничить...</description><pubDate>Mon, 09 Feb 2026 08:01:08 GMT</pubDate><content:encoded>&lt;p&gt;За последние пару месяцев видел пару публикаций у знакомых про отказ от соц сетей или их осознанное ограничение. Я любитель поскролить ленту и насытиться лёгким дофамином, так что для меня тема более чем актуальная, поэтому я начал пользоваться &lt;a href=&quot;https://one-sec.app/&quot;&gt;One Sec.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;❓ &lt;strong&gt;Что такое One Sec?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Это приложение, которое помогает ограничить необдуманные открытия других приложений.&lt;/p&gt;
&lt;p&gt;Ну, знаете, как это бывает: билд запустил, или что-то загружается дольше пары секунд — и ты уже ушёл скролить ленту на несколько минут&lt;/p&gt;
&lt;p&gt;Но One Sec не даст вам мгновенно открыть запретграм, телегу или куда там у вас тянутся руки в моменты скуки.&lt;/p&gt;
&lt;p&gt;Вместо этого One Sec покажет экран с предложением &lt;strong&gt;«Сделайте глубокий вдох…» секунд так на 10&lt;/strong&gt; и заодно отобразит, сколько раз за последние 24 часа вы пытались открыть приложение.&lt;/p&gt;
&lt;p&gt;Примерно два месяца назад я поставил такое ограничение на запретграм — и теперь счётчик в будние дни редко показывает больше &lt;strong&gt;2 раз за 24 часа&lt;/strong&gt;, хотя до этого он легко доходил до 50.&lt;/p&gt;
&lt;p&gt;Когда знаешь, что приложение не откроется мгновенно, желание зайти туда как-то само пропадает 🤷‍♂️.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;⚙️ Настраивается всё довольно быстро&lt;/strong&gt;, через автоматизации айфона:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Когда открывается определённое приложение&lt;/li&gt;
&lt;li&gt;🅰 Активировать one sec&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;На прошлой неделе поставил ограничения ещё и на телегу и ВК. Тут есть нюанс: в них я часто переписываюсь, особенно сейчас, когда идёт ремонт, а не только листаю ленту или читаю каналы.&lt;/p&gt;
&lt;p&gt;Поэтому пришлось настроить &lt;strong&gt;«Быстрое переключение»&lt;/strong&gt; — чтобы экран с ожиданием не показывался, если я вернулся в приложение в течение 5 минут.&lt;/p&gt;
&lt;p&gt;📊 &lt;strong&gt;Результаты&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;После того как я стал &lt;strong&gt;реже открывать запретграм&lt;/strong&gt;, быстрый дофамин начал искаться в других местах — и в итоге я стал чаще заходить в ВК, телегу и сетку. Так что one sec пришлось поставить и на них тоже.&lt;/p&gt;
&lt;p&gt;В целом штука рабочая 👍.&lt;/p&gt;
&lt;p&gt;Она реально сбивает импульсивное желание открыть соцсети, и за счёт этого концентрация на важных вещах становится заметно лучше.&lt;/p&gt;
&lt;p&gt;Ставьте:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👍 Если пользуетесь приложениями типа one sec&lt;/li&gt;
&lt;li&gt;❤️ Если у вас нет проблем с думскроллингом&lt;/li&gt;
&lt;li&gt;🤪 Если любите залипнуть в соц сетях&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#burnout #productivity&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-429-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-429-1.jpg"/></item><item><title>🎭 Про маски</title><link>https://cherkashin.dev/posts/428/</link><guid isPermaLink="true">https://cherkashin.dev/posts/428/</guid><description>🎭 Про маски

У нас наметился очередной редизайн, и снова всплыла проблема, с которой мы живём уже очень долго — зоопарк иконок.

Если кратко: мы не можем инлайнить SVG или использовать что-нибудь вроде Font Awesome, потому что у пользователя должна быть возможность кастомизировать любую иконку в продукте. А само решен...</description><pubDate>Wed, 04 Feb 2026 08:56:28 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🎭 Про маски&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;У нас наметился очередной редизайн, и снова всплыла проблема, с которой мы живём уже очень долго — зоопарк иконок.&lt;/p&gt;
&lt;p&gt;Если кратко: мы не можем инлайнить SVG или использовать что-нибудь вроде Font Awesome, потому что у пользователя должна быть возможность кастомизировать &lt;strong&gt;любую&lt;/strong&gt; иконку в продукте. А само решение было реализовано лет так 7 назад.&lt;/p&gt;
&lt;p&gt;В итоге все иконки подгружаются через &lt;code&gt;background-image&lt;/code&gt;, а это значит, что если нужно изменить цвет иконки по ховеру — придётся подгружать &lt;strong&gt;новую&lt;/strong&gt; иконку (спрайты тоже не можем использовать).&lt;/p&gt;
&lt;p&gt;Выглядит это примерно вот так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.icon&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; background-image&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;./icon.svg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x26;:hover,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x26;:focus-visible {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  background-image: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;./icon-hover.svg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x26;--active {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  background-image&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;./icon-active.svg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;🫠 В 2026 году подход, конечно, &lt;del&gt;||пиздец||&lt;/del&gt; очень грустный.&lt;/p&gt;
&lt;p&gt;Из-за этого каждая иконка дублируется в среднем 3 раза. Представляете, сколько времени занимает добавить новую иконку…&lt;/p&gt;
&lt;p&gt;Но, как ни крути, &lt;strong&gt;идёт 2026 год&lt;/strong&gt;, и теперь мы можем использовать CSS-маски — &lt;code&gt;mask-image&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;По сути, мы просто указываем цвет фона, а в качестве маски выступает иконка. В итоге получается, что мы её просто перекрашиваем:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.icon&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; mask-image&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;./icon.svg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; background-color&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;--icon-color&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x26;:hover,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x26;:focus-visible {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  background-color: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;--icon-color-hover&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x26;--active {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  background-color&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;--icon-color-active&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;В итоге, чтобы поменять цвет иконки, достаточно изменить &lt;code&gt;background-color&lt;/code&gt;. А если иконка используется в кнопке, можно воспользоваться &lt;code&gt;currentColor&lt;/code&gt; — ровно так же, как и для SVG.&lt;/p&gt;
&lt;p&gt;Может, выглядит так себе (хотя вроде норм, да и выбора у нас всё равно нет), зато у подхода есть ряд преимуществ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;из коробки работает асинхронная загрузка — не будет проблемы с раздутым бандлом;&lt;/li&gt;
&lt;li&gt;HTML-разметка не раздувается из-за инлайна SVG;&lt;/li&gt;
&lt;li&gt;частично решает проблему зоопарка иконок, так как не нужно хранить иконку для каждого цвета.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1️⃣ Если у вас иконки инлайнятся и раздувают бандлы, советую посмотреть доклад&lt;br&gt;
&lt;a href=&quot;https://youtu.be/nVw6MZA8oTE?t=4&quot;&gt;SVG в React: как автоматизировать процесс добавления новых иконок&lt;/a&gt; с прошлого «Я 💛 Фронтенд».&lt;br&gt;
Там рассказано, как решили проблему жирного бандла в Centra — с помощью динамического &lt;a href=&quot;https://github.com/kovalyovkirill/svg-async-load/blob/main/src/atoms/Icon/hook.ts&quot;&gt;импорта иконок&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;2️⃣ А если вам интересно как с зоопарком иконок боролись в VK — посмотрите доклад &lt;a href=&quot;https://www.youtube.com/watch?v=PgQ2CiNYdYM&quot;&gt;Зоопарк иконок: упрощаем работу с иконками для дизайна и разработки&lt;/a&gt;. Оказывается дизайнеров тоже можно научить пользоваться гитом и сбросить всю ответственность за иконки на них 😅.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Давайте сверимся по иконкам:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👍 — не знал про &lt;code&gt;mask-image&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;❤️ — использую библиотечные иконки и нет проблем&lt;/li&gt;
&lt;li&gt;🔥 — просто инлайню SVG&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend #css&lt;/p&gt;</content:encoded></item><item><title>Недавно нашу компанию объединили с другой, которая также разрабатывает no-code платформу. И сейчас…</title><link>https://cherkashin.dev/posts/427/</link><guid isPermaLink="true">https://cherkashin.dev/posts/427/</guid><description>Недавно нашу компанию объединили с другой, которая также разрабатывает no-code платформу. И сейчас мы знакомимся с новой командой разработки и активно обмениваемся знаниями. Так как наши продукты похожи, интересно посмотреть как у них всё реализовано.

На прошлой неделе лид AI-команды рассказывал, как в их продукте уст...</description><pubDate>Mon, 26 Jan 2026 10:32:28 GMT</pubDate><content:encoded>&lt;p&gt;Недавно нашу компанию объединили с другой, которая также разрабатывает no-code платформу. И сейчас мы знакомимся с новой командой разработки и активно обмениваемся знаниями. Так как наши продукты похожи, интересно посмотреть как у них всё реализовано.&lt;/p&gt;
&lt;p&gt;На прошлой неделе лид AI-команды рассказывал, как в их продукте устроены ИИ-агенты и как используется RAG. Попробую кратко вам рассказать.&lt;/p&gt;
&lt;p&gt;🤖 &lt;strong&gt;Чем вообще ИИ агент отличается от обычной программы?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ключевые отличия заключаются в двух возможностях: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;использовании инструментов &lt;/li&gt;
&lt;li&gt;динамическом принятии решений​&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Под инструментами может подразумеваться:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://platform.openai.com/docs/guides/function-calling&quot;&gt;function calling&lt;/a&gt; — мы описываем, с какими функциями в нашем коде ИИ может взаимодействовать. Конечно, ИИ не запускает код напрямую: он генерирует имя функции и входные параметры, а сам вызов мы делаем уже со своей стороны.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://platform.openai.com/docs/guides/tools&quot;&gt;tools use&lt;/a&gt; — более высокоуровневые инструменты: поиск в интернете, работа с файлами, генерация картинок и так далее.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А благодаря тому, что у LLM есть условные «мозги», она сама понимает, какие инструменты и в какой последовательности вызывать и когда остановиться. Это и есть то самое &lt;strong&gt;динамическое принятие решений&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;📚 Теперь кратко про RAG.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;RAG — это генерация ответа, дополненная поиском по вашим данным, о которых сама LLM знать не может. Например, по корпоративной базе знаний.&lt;/p&gt;
&lt;p&gt;Пример задачи: «Нам нужно, чтобы LLM отвечала на вопросы с учётом загруженных пользователями PDF-файлов».&lt;/p&gt;
&lt;p&gt;Как это реализуется:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;преобразуем PDF в текст&lt;/li&gt;
&lt;li&gt;разбиваем текст на чанки&lt;/li&gt;
&lt;li&gt;каждый чанк превращаем в векторное представление (эмбеддинг) с помощью embedding-модели&lt;/li&gt;
&lt;li&gt;сохраняем текст вместе с вектором, например в Postgres с плагином pgvector&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Кстати, на прошлой неделе нашёл отличную статью про то, как слова превращаются в векторы и используются в поиске. Скоро поделюсь 🔜.&lt;/p&gt;
&lt;p&gt;Дальше, когда пользователь задаёт вопрос:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;запрос преобразуется в вектор&lt;/li&gt;
&lt;li&gt;находится наиболее подходящая по смыслу запись&lt;/li&gt;
&lt;li&gt;в LLM передаётся: вопрос + найденные куски текста&lt;/li&gt;
&lt;li&gt;LLM формирует ответ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Часть команды, немного растерялась, когда тимлид из другой платформы рассказывал обо всём этом 😅, так как большинство из нас ещё не сталкивались с разработкой агентов.&lt;/p&gt;
&lt;p&gt;Сам я ИИ-агентов ещё не разрабатывал — пока разбираюсь в теме на уровне теории. В &lt;a href=&quot;https://www.guidedao.xyz/ru&quot;&gt;Guide DAO&lt;/a&gt; успел пройти только теоретическую часть курса по разработке &lt;a href=&quot;https://www.guidedao.xyz/agents?utm_source=utm_source%3Dtutortop&amp;#x26;utm_term=5e60b822-1443-45dd-ba3c-a996bb9d5633&quot;&gt;ИИ-агентов&lt;/a&gt;, так что как минимум понимаю, о чём вообще идёт речь 😅. Если кто-то пропустил, Guide DAO — это образовательное комьюнити про разработку в web3 и &lt;a href=&quot;https://www.guidedao.xyz/agents?utm_source=utm_source%3Dtutortop&amp;#x26;utm_term=5e60b822-1443-45dd-ba3c-a996bb9d5633&quot;&gt;ИИ-агентов&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;🏷 До конца января у ребят действует акция — скидка 20%, плюс по промокоду &lt;code&gt;CHERKASHIN&lt;/code&gt; можно получить дополнительную скидку 25%. В сумме — 45%.&lt;/p&gt;
&lt;p&gt;А в марте запускается живой курс по вайбкодингу на 2 месяца (теория + практика + созвоны со спикером) &lt;a href=&quot;https://www.linkedin.com/in/amyote/&quot;&gt;Алексеем Аметовым&lt;/a&gt; в качестве спикера. Каждый будет решать свою задачу и учиться прямо на её примере. А при &lt;a href=&quot;https://www.guidedao.xyz/agents?utm_source=utm_source%3Dtutortop&amp;#x26;utm_term=5e60b822-1443-45dd-ba3c-a996bb9d5633&quot;&gt;покупке курса по ИИ-агентам&lt;/a&gt; живой курс по вайбкодингу идёт в подарок.&lt;/p&gt;
&lt;p&gt;Ставьте:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❤️ — если интересно читать про ИИ-агентов&lt;/li&gt;
&lt;li&gt;🔥 — если уже понимаете, как они работают&lt;/li&gt;
&lt;li&gt;👀 — если до изучения агентов пока не дошли руки&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-427-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-427-1.jpg"/></item><item><title>🎉 Приглашение получено!</title><link>https://cherkashin.dev/posts/421/</link><guid isPermaLink="true">https://cherkashin.dev/posts/421/</guid><description>🎉 Приглашение получено!

Это будет уже третий «Я 💛 Фронтенд», на который я отправлюсь.

Я вообще люблю ездить на конференции, организованные Яндексом — будь то «Я 💛 Фронтенд», Субботник или «Ночь в Музее». Там всегда отличная атмосфера, классные доклады и афтепати. А ещё это отличный способ завести новые знакомства ...</description><pubDate>Sun, 25 Jan 2026 07:44:59 GMT</pubDate><content:encoded>&lt;p&gt;🎉 &lt;strong&gt;Приглашение получено!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Это будет уже третий «Я 💛 Фронтенд», на который я отправлюсь.&lt;/p&gt;
&lt;p&gt;Я вообще люблю ездить на конференции, организованные Яндексом — будь то «Я 💛 Фронтенд», Субботник или «Ночь в Музее». Там всегда отличная атмосфера, классные доклады и афтепати. А ещё это отличный способ завести новые знакомства и найти ответы на вопросы, которые давно крутятся в голове.&lt;/p&gt;
&lt;p&gt;Пару лет назад по приколу подал заявку на Субботник в Питере — и, как ни странно, её одобрили. И вот я уже покупаю билет на поезд «Курск — Санкт-Петербург». Фотки на которых я такой помятый именно из Питера 😅.&lt;/p&gt;
&lt;p&gt;В общем:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❤️ — если тоже идёте на «Я 💛 Фронтенд»&lt;/li&gt;
&lt;li&gt;👀 — если будете смотреть онлайн&lt;/li&gt;
&lt;li&gt;🤔 — если пока не определились&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А если вы ещё не подали заявку, то &lt;a href=&quot;https://events.yandex.ru/events/ya-love-frontend-2026&quot;&gt;скорее регистрируйтесь&lt;/a&gt;, и увидимся 14 февраля 👋.&lt;/p&gt;
&lt;p&gt;#conference&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-421-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-421-1.jpg"/></item><item><title>jQuery 4️⃣.0️⃣</title><link>https://cherkashin.dev/posts/420/</link><guid isPermaLink="true">https://cherkashin.dev/posts/420/</guid><description>jQuery 4️⃣.0️⃣

Мы всё проспали, вчера вышел JQuery 4.0.
Предыдущий релиз был 9 июня 2016 года.

А говорят он умер, может ещё и реакт переживёт 😅. У нас вот, к сожалению, полно легаси на JQuery...

https://blog.jquery.com/2026/01/17/jquery-4-0-0/

Давайте разберёмся, кто здесь весь в легаси:

🤬 — у нас много легаси н...</description><pubDate>Mon, 19 Jan 2026 08:50:18 GMT</pubDate><content:encoded>&lt;p&gt;**jQuery &lt;strong&gt;4️⃣&lt;/strong&gt;.**0️⃣&lt;/p&gt;
&lt;p&gt;Мы всё проспали, вчера вышел JQuery 4.0.
Предыдущий релиз был &lt;strong&gt;9 июня 2016 года&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;А говорят он умер, может ещё и реакт переживёт 😅. У нас вот, к сожалению, полно легаси на JQuery…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.jquery.com/2026/01/17/jquery-4-0-0/&quot;&gt;https://blog.jquery.com/2026/01/17/jquery-4-0-0/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Давайте разберёмся, кто здесь весь в легаси:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🤬 — у нас много легаси на JQuery&lt;/li&gt;
&lt;li&gt;🥱 — есть, но чуть-чуть&lt;/li&gt;
&lt;li&gt;👍 — использую только новые фреймворки&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend&lt;/p&gt;</content:encoded></item><item><title>📱 Настройка синхронизации Obsidian на iPhone</title><link>https://cherkashin.dev/posts/417/</link><guid isPermaLink="true">https://cherkashin.dev/posts/417/</guid><description>📱 Настройка синхронизации Obsidian на iPhone

После переезда с Notion на Obsidian главной болью (не считая баз данных) оказалось отсутствие нормальной синхронизации с iPhone.На праздниках наконец решил это исправить.

Интеграция с Git у меня уже была настроена, оставалось самое сложное — подружить всё это с айфоном.

...</description><pubDate>Thu, 15 Jan 2026 09:02:33 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;📱 Настройка синхронизации Obsidian на iPhone&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;После переезда с Notion на Obsidian главной болью (не считая баз данных) оказалось отсутствие нормальной синхронизации с iPhone.&lt;br&gt;
На праздниках наконец решил это исправить.&lt;/p&gt;
&lt;p&gt;Интеграция с Git у меня уже была настроена, оставалось самое сложное — подружить всё это с айфоном.&lt;/p&gt;
&lt;p&gt;👉 **Подробная инструкция — **&lt;a href=&quot;https://youtu.be/Cu4-BPcveBI?t=912&quot;&gt;вот здесь&lt;/a&gt;&lt;br&gt;
А если кратко, то схема такая:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Настраиваем &lt;a href=&quot;https://github.com/Vinzent03/obsidian-git&quot;&gt;интеграцию с Git&lt;/a&gt; в Obsidian на компьютере&lt;/li&gt;
&lt;li&gt;Устанавливаем &lt;a href=&quot;https://apps.apple.com/us/app/obsidian-connected-notes/id1557175442&quot;&gt;Obsidian на iPhone&lt;/a&gt; и создаём пустой Vault&lt;/li&gt;
&lt;li&gt;Затем ставим &lt;a href=&quot;https://apps.apple.com/nl/app/gitsync/id6744980427&quot;&gt;GitSync&lt;/a&gt; - Git-клиент для iPhone, который умеет работать с репозиториями&lt;/li&gt;
&lt;li&gt;Логинимся и пуллим свой Obsidian-репозиторий через GitSync&lt;/li&gt;
&lt;li&gt;Заходим в Obsidian и &lt;strong&gt;выключаем Git-плагин&lt;/strong&gt;, чтобы не было конфликтов&lt;/li&gt;
&lt;li&gt;Включаем автоматическую синхронизацию репозитория в GitSync. Я пока оставил ручную, записал небольшую демку.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ставьте:&lt;br&gt;
👍 — если используете Obsidian&lt;br&gt;
😐 — если всё ещё на Notion&lt;br&gt;
😱 — если вообще ничего не используете для ведения заметок&lt;/p&gt;
&lt;p&gt;#obsidian&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-418-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-418-1.jpg"/></item><item><title>Лет 6 назад мы начали мигрировать на React и для быстрого старта взяли CRA. С тех пор много воды…</title><link>https://cherkashin.dev/posts/416/</link><guid isPermaLink="true">https://cherkashin.dev/posts/416/</guid><description>Лет 6 назад мы начали мигрировать на React и для быстрого старта взяли CRA. С тех пор много воды утекло и этой осенью я и ещё один коллега начали искать альтернативы CRA.

Естественно, времени на это никто не выделял, поэтому нужно было отделаться &quot;малой кровью&quot;. 

Попытка 1️⃣

Многие пишут, что буквально за полчаса ми...</description><pubDate>Mon, 12 Jan 2026 08:27:31 GMT</pubDate><content:encoded>&lt;p&gt;Лет 6 назад мы начали мигрировать на React и для быстрого старта взяли CRA. С тех пор много воды утекло и этой осенью я и ещё один коллега начали искать альтернативы CRA.&lt;/p&gt;
&lt;p&gt;Естественно, времени на это никто не выделял, поэтому нужно было отделаться “малой кровью”. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Попытка 1️⃣&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Многие пишут, что буквально за полчаса мигрируют на Vite. Но есть нюанс: у нас не чистый CRA, а форк (&lt;a href=&quot;https://habr.com/ru/articles/866158/&quot;&gt;подробнее тут&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Большая часть конфигурации оказалась довольно простой:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vite по умолчанию поддерживает глобальные константы через &lt;a href=&quot;https://vite.dev/config/shared-options#define&quot;&gt;define&lt;/a&gt; и &lt;a href=&quot;https://vite.dev/config/shared-options#resolve-alias&quot;&gt;алиасы&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Мы поправили импорты SVG-файлов&lt;/li&gt;
&lt;li&gt;Нашли, как обойти ограничение для &lt;code&gt;umd&lt;/code&gt; и &lt;code&gt;iife&lt;/code&gt; форматов, когда указано несколько энтрипоинтов&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Но дальше мы упёрлись в неприятный момент.&lt;/p&gt;
&lt;p&gt;⚠️ Мы встраиваемся в legacy-проект, где старый код ожидает &lt;strong&gt;синхронную загрузку скриптов&lt;/strong&gt;.&lt;br&gt;
А скрипты, собранные через Vite, нужно подключать с &lt;code&gt;&amp;#x3C;script type=&quot;module&quot;&gt;&lt;/code&gt;, который всегда асинхронный — сделать его блокирующим не получится. Убрать &lt;code&gt;type=&quot;module&quot;&lt;/code&gt; не выйдет иначе получите ошибку “Cannot use import statement outside a module”.&lt;/p&gt;
&lt;p&gt;В итоге из-за асинхронной загрузки посыпалось довольно много всего.&lt;/p&gt;
&lt;p&gt;Возможно, если бы продолжили, мы бы столкнулись и с другими проблемами. Но мы решили поискать альтернативные решения, хотя мигрировать на vite, конечно было возможно, но искать косяки во всём приложении не захотели.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Попытка 2️⃣&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Мы продолжили исследование и &lt;a href=&quot;https://medium.com/@sauravtiru/how-i-decreased-our-react-app-build-time-by-96-26-webpack-esbuild-part-2-a692f4793e3f&quot;&gt;наткнулись на статью&lt;/a&gt; про замену &lt;code&gt;babel-loader&lt;/code&gt; на &lt;code&gt;esbuild-loader&lt;/code&gt; для ускорения сборки.&lt;/p&gt;
&lt;p&gt;Решили попробовать. Вся магия из статьи сводится к простым шагам:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;заменяем &lt;code&gt;babel-loader&lt;/code&gt; на &lt;code&gt;esbuild-loader&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TerserPlugin&lt;/code&gt; — на &lt;code&gt;EsbuildPlugin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;⏱ Скорость билда выросла примерно на &lt;strong&gt;30%&lt;/strong&gt; (30 =&gt; 21 секунды)— уже приятно.&lt;/p&gt;
&lt;p&gt;Но тут вылезла другая проблема: esbuild пока плохо справляется с tree shaking динамических импортов, и итоговый бандл раздулся почти в &lt;strong&gt;2 раза&lt;/strong&gt; &lt;a href=&quot;https://github.com/privatenumber/esbuild-loader/issues/178#issuecomment-848077334&quot;&gt;пруф 1&lt;/a&gt;,  &lt;a href=&quot;https://github.com/evanw/esbuild/issues/4255&quot;&gt;пруф 2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;И тут мы снова вспомнили про Vite.&lt;/p&gt;
&lt;p&gt;🎉 &lt;strong&gt;Попытка 3️⃣&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Вдохновившись подходом Vite, мы решили пойти гибридным путём и комбинировать &lt;code&gt;esbuild&lt;/code&gt; и &lt;code&gt;babel&lt;/code&gt; для разных сценариев:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;esbuild-loader&lt;/code&gt; — для разработки&lt;/li&gt;
&lt;li&gt;&lt;code&gt;babel-loader&lt;/code&gt; — для продакшена&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В итоге нам удалось:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ускорить билд&lt;/li&gt;
&lt;li&gt;сохранить размер бандла&lt;/li&gt;
&lt;li&gt;и, что важно, уехать с CRA&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CRA мы просто эджекнули, апгрейднули зависимости и внесли необходимые изменения под esbuild.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Был ещё один очень простой трюк, который позволил ускорить билд, ведь изначальное время билда было — 1 минута, но об этом в другой раз.&lt;/p&gt;
&lt;p&gt;Расскажите, чем вы собираете свой фронтенд или ставьте:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;😢 — если у вас всё ещё Create React App&lt;/li&gt;
&lt;li&gt;👍 — если у вас Vite&lt;/li&gt;
&lt;li&gt;🔥 — если у вас нестандартная сборка&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-416-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-416-1.jpg"/></item><item><title>Это уже третий год подряд, когда я сажусь, навожу кофе и не спеша подвожу итоги уходящего года. В…</title><link>https://cherkashin.dev/posts/406/</link><guid isPermaLink="true">https://cherkashin.dev/posts/406/</guid><description>Это уже третий год подряд, когда я сажусь, навожу кофе и не спеша подвожу итоги уходящего года. В этот раз, чтобы сделать процесс чуть проще, я подводил небольшие итоги каждый месяц.

Как ни странно, в этом году я реализовал все важные цели, которые ставил в начале года:

🚗 Получил водительские права🚙 Купил машину. З...</description><pubDate>Tue, 30 Dec 2025 08:08:58 GMT</pubDate><content:encoded>&lt;p&gt;Это уже третий год подряд, когда я сажусь, навожу кофе и не спеша подвожу итоги уходящего года. В этот раз, чтобы сделать процесс чуть проще, я подводил небольшие итоги каждый месяц.&lt;/p&gt;
&lt;p&gt;Как ни странно, в этом году я реализовал &lt;strong&gt;все важные цели&lt;/strong&gt;, которые ставил в начале года:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🚗 Получил водительские права&lt;/li&gt;
&lt;li&gt;🚙 Купил машину. Знали бы вы, как меня колотило, когда я без инструктора сел и поехал ставить её на учёт 🤣&lt;/li&gt;
&lt;li&gt;🛠 Начал ремонт в квартире&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это всё — то, что я откладывал очень долго. И почему-то годами думал: «ну не получится, не моё».  Но именно в этом году я вдруг понял, что &lt;strong&gt;я могу&lt;/strong&gt;. Во многом — благодаря тому, что наконец-то расставил приоритеты.&lt;/p&gt;
&lt;p&gt;💼 &lt;strong&gt;О работе&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;10 месяцев назад меня &lt;a href=&quot;https://t.me/cherkashindev/331&quot;&gt;сделали тимлидом,&lt;/a&gt; и я понял, что раньше моя жизнь была сказкой 😅.
Поначалу было очень сложно осознать, чем теперь вообще нужно заниматься и какие у меня обязанности. Но, кажется, я справился.&lt;/p&gt;
&lt;p&gt;А ещё мы нашли &lt;a href=&quot;https://t.me/cherkashindev/387&quot;&gt;стабильный способ&lt;/a&gt; получать свои кровно заработанные зелёные.&lt;/p&gt;
&lt;p&gt;✈️ &lt;strong&gt;Путешествия&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Провёл прошлые новогодние праздники в русской сказке — &lt;a href=&quot;https://t.me/cherkashindev/270&quot;&gt;🇷🇺 Суздаль и Владимир&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Впервые слетал в 🇦🇪 Дубай и офигел &lt;a href=&quot;https://t.me/cherkashindev/302&quot;&gt;от красоты и масштаба,&lt;/a&gt; но понял, что во всём этом сильно не хватает души&lt;/li&gt;
&lt;li&gt;Получил первый шенген и съездил в:
&lt;ul&gt;
&lt;li&gt;🇫🇷 Париж — надеюсь, дойдут руки разобрать заметки и написать отдельный пост. В целом там невероятно красиво, хотя и есть нюансы…&lt;/li&gt;
&lt;li&gt;🇮🇹 Рим — честно, после Парижа Рим как-то не зашёл. Кажется, было настолько многолюдно, что мы просто не смогли кайфануть&lt;/li&gt;
&lt;li&gt;🇻🇦 Ватикан — отправил открытку из Ватикана и получил её в Курске&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ну и завершает цепочку спокойная поездка &lt;a href=&quot;https://t.me/cherkashindev/354&quot;&gt;в 🇷🇺 Питер и Выборг&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📚 &lt;strong&gt;Обучение&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Бывают же совпадения: как только я стал тимлидом, мне предложили пройти курс Стратоплана.&lt;/p&gt;
&lt;p&gt;Совмещать обучение с вождением было непросто, но, честно говоря, я кайфанул. Как же круто, когда ты не собираешь знания по крупинкам, а получаешь всё сразу — на блюдечке с голубой каёмочкой.&lt;/p&gt;
&lt;p&gt;Также прочитал вступление &lt;a href=&quot;https://t.me/cherkashindev/397&quot;&gt;курса о разработке AI-агентов,&lt;/a&gt; разобрался с основами архитектуры агентов, что такое RAG, но решил, что для этого года уже достаточно — продолжу после новогодних.&lt;/p&gt;
&lt;p&gt;🎤 &lt;strong&gt;Конференции&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Успел немного поездить по конференциям:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/291&quot;&gt;Я 💛 Фронтенд&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Big Tech Night&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/396&quot;&gt;AI Boost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/399&quot;&gt;Сетка&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📢 &lt;strong&gt;Про канал&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Канал за год немного подрос, но совсем чуть-чуть. В этом году некогда было заниматься его ростом.&lt;/p&gt;
&lt;p&gt;Зато давно было интересно, как авторы продают рекламу. В этом году наконец-то разобрался и опубликовал несколько рекламных постов. Но это мелочь. Гораздо важнее, что благодаря каналу попал в &lt;a href=&quot;https://t.me/cherkashindev/331&quot;&gt;Стратоплан,&lt;/a&gt; &lt;a href=&quot;https://t.me/cherkashindev/321&quot;&gt;Сетку,&lt;/a&gt; &lt;a href=&quot;https://t.me/cherkashindev/396&quot;&gt;AI Boost&lt;/a&gt; и &lt;a href=&quot;https://www.guidedao.xyz/&quot;&gt;guidedao.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;То, что канал не только забирает силы, но и даёт новые возможности, конечно, сильно мотивирует.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;К счастью, плохого в этом году ничего не было, разве что +3кг на моих щеках)))&lt;/p&gt;
&lt;p&gt;Для меня этот год оказался &lt;strong&gt;в разы лучше предыдущего&lt;/strong&gt;.  Но самое главное — я стал лучше расставлять жизненные приоритеты и к концу года всё-таки смог выпрыгнуть из колеса, в котором крутился как белка последние несколько лет.&lt;/p&gt;
&lt;p&gt;А ещё начал понимать, что не нужно гнаться за успешным успехом. Очень легко хотеть то, что есть у других, и куда сложнее — заглянуть внутрь себя и понять, что на самом деле нужно именно тебе.&lt;/p&gt;
&lt;p&gt;Желаю всем понять это в наступающем новом году. 🎄&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/260&quot;&gt;Итоги года 2024&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/151&quot;&gt;Итоги года 2023&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ставьте&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👍 — если тоже подводите итоги года&lt;/li&gt;
&lt;li&gt;🎉 — какие итоги? я дожил до нового года&lt;/li&gt;
&lt;li&gt;🎄 — наряженная ёлка — вот мой главный итог&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#newyear #итогигода&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-406-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-406-1.jpg"/></item><item><title>😕 Все эти слухи про блокировки не могут не расстраивать. Особенно про Телеграм, когда начинаешь…</title><link>https://cherkashin.dev/posts/399/</link><guid isPermaLink="true">https://cherkashin.dev/posts/399/</guid><description>😕 Все эти слухи про блокировки не могут не расстраивать. Особенно про Телеграм, когда начинаешь думать о том, что все силы, вложенные в канал, могут в один момент испариться.

Я задумался чем мне нравится телеграмм и понял. В нем нет ленты, ты не зависишь от дурацких алгоритмов, которые сегодня решат, что тебя увидят ...</description><pubDate>Thu, 18 Dec 2025 09:21:42 GMT</pubDate><content:encoded>&lt;p&gt;😕 Все эти слухи про блокировки не могут не расстраивать. Особенно про Телеграм, когда начинаешь думать о том, что все силы, вложенные в канал, могут в один момент испариться.&lt;/p&gt;
&lt;p&gt;Я задумался чем мне нравится телеграмм и понял. В нем нет ленты, ты не зависишь от дурацких алгоритмов, которые сегодня решат, что тебя увидят тысячи людей, а завтра ноль.&lt;/p&gt;
&lt;p&gt;Просмотры напрямую коррелируют с числом подписчиков. Если люди на тебя подписались, они сами решают, читать твой пост или нет, а не дурацкие алгоритмы.&lt;/p&gt;
&lt;p&gt;А ещё, ты можешь пропасть на неопределённое время, и алгоритмы не выкинут тебя из рекомендации, поэтому нет этой гонки постинга, когда нужно публиковать что-то каждую неделю, чтобы не выбыть из гонки.&lt;/p&gt;
&lt;p&gt;Надеюсь, слухи о блокировке преувеличены. Хотя айтишная аудитория прекрасно обходит ограничения, всё же хотелось бы понять, как диверсифицировать риски.&lt;/p&gt;
&lt;p&gt;Я пробовал:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Пикабу — токсичнее площадки не найти&lt;/li&gt;
&lt;li&gt;Дзен — то, что мертво умереть не может, но Дзен смог, активности 0&lt;/li&gt;
&lt;li&gt;Хабр — посты мне как-то на Хабре не зашли, или просто формат моих постов не подходит для хабра&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Единственная альтернаивная площадка которую я Веду — &lt;a href=&quot;https://setka.ru/communities/0195be6f-3ed1-4597-83d5-d3c4e50f66a0&quot;&gt;Сетка&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;🎄 Кстати, на прошлой неделе, меня позвали на Новогоднюю Вечеринку Сетки как автора канала тысячника. А ещё прислали мерч в Июле, который я совсем забыл показать.&lt;/p&gt;
&lt;p&gt;#telegram  #сетка&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-399-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-399-1.jpg"/></item><item><title>Пару месяцев назад закончилось моё обучение в Стратоплане, поэтому захотелось подвести небольшие…</title><link>https://cherkashin.dev/posts/398/</link><guid isPermaLink="true">https://cherkashin.dev/posts/398/</guid><description>Пару месяцев назад закончилось моё обучение в Стратоплане, поэтому захотелось подвести небольшие итоги.

🔥 Самое важное — я почувствовал рост. Но конечно, я не стал мгновенно классным руководителем. Ни один курс не заменит вам реальный опыт и шишки, которые каждый должен набить сам.

Но та база, что закладывается в пр...</description><pubDate>Mon, 08 Dec 2025 08:29:11 GMT</pubDate><content:encoded>&lt;p&gt;Пару месяцев назад закончилось &lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;моё обучение в Стратоплане&lt;/a&gt;, поэтому захотелось подвести небольшие итоги.&lt;/p&gt;
&lt;p&gt;🔥 &lt;strong&gt;Самое важное — я почувствовал рост.&lt;/strong&gt; Но конечно, я не стал мгновенно классным руководителем. Ни один курс не заменит вам реальный опыт и шишки, которые каждый должен набить сам.&lt;/p&gt;
&lt;p&gt;Но та база, что закладывается в программе, в сочетании с практикой в группе — реально работает. Главное продолжать возвращаться к материалам и закреплять всё это на рабочей практике&lt;/p&gt;
&lt;p&gt;📚 &lt;strong&gt;Материала было много — очень много.&lt;/strong&gt; Я осилил только основной курс, хотя есть ещё 5 дополнительных, на которые у меня просто не хватило сил:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Проектный менеджмент&lt;/li&gt;
&lt;li&gt;Технический продакт-менеджмент&lt;/li&gt;
&lt;li&gt;Карьера&lt;/li&gt;
&lt;li&gt;Стратегия&lt;/li&gt;
&lt;li&gt;Собеседование / найм / увольнение&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Доступ к материалам пожизненный, поэтому вернусь к ним уже в следующем году, когда немного восстановлюсь.&lt;/p&gt;
&lt;p&gt;Если вам интересен материал модулей, то здесь собраны все описания:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/334&quot;&gt;Модуль 1 — Командообразование, часть 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/337&quot;&gt;Модуль 1 — Командообразование, часть 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/344&quot;&gt;Модуль 2 — Постановка задач, делегирование, фидбек&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/351&quot;&gt;Модуль 3 —Управление ожиданиями&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/367&quot;&gt;Модуль 4 — Встречи 1:1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/385&quot;&gt;Модуль 5 — Лидерство&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А ещё пару недель назад, в баре, болтал с товарищами и внезапно узнал, что один из них тоже проходил обучение в Стратоплане — но уже на курсе для CTO. И он подтвердил, что курсы там действительно крутые.&lt;/p&gt;
&lt;p&gt;Так что, если вдруг решитесь пройти обучение — &lt;a href=&quot;https://t.me/cherkalexander&quot;&gt;напишите мне&lt;/a&gt;, поделюсь промокодом на скидку в 15%.&lt;/p&gt;
&lt;p&gt;🎁 Кстати, сейчас возможность подсмотреть, как проходит обучение в Стратоплане. Если вам хочется получить доступ к модулям Курса стратегия — есть один способ.&lt;/p&gt;
&lt;p&gt;Стратоплан совместно с DevCrowd запустил &lt;a href=&quot;https://stratoplan-school.com/research/&quot;&gt;исследование про стратегию&lt;/a&gt;, чтобы понять, как у компаний и сотрудников обстоят дела со стратегией, её каскадированием, разработкой и внедрением.&lt;/p&gt;
&lt;p&gt;Каждый, кто потратит буквально 10 минут, и &lt;a href=&quot;https://stratoplan-school.com/research/&quot;&gt;пройдет опрос&lt;/a&gt;, сможет получить доступ к модулю Стратегия.&lt;/p&gt;
&lt;p&gt;Расскажите, а как вы смотрите в сторону менеджерского роста:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔥 Уже руковожу командой&lt;/li&gt;
&lt;li&gt;👍 Планирую стать руководителем в будущем&lt;/li&gt;
&lt;li&gt;👨‍💻 Просто хочу быть сильным разработчиком&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-398-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-398-1.jpg"/></item><item><title>Я думаю вы слышали об исследованиях, в которых выясняется, что ИИ на самом деле может не ускорять,…</title><link>https://cherkashin.dev/posts/397/</link><guid isPermaLink="true">https://cherkashin.dev/posts/397/</guid><description>Я думаю вы слышали об исследованиях, в которых выясняется, что ИИ на самом деле может не ускорять, а замедлять разработку? Но, как обычно, все концентрируются на времени, забывая, что у нас не только времени, но и ума не хватает. 

Иногда я работаю и время то у меня есть, но вот силы уже на исходе. И тогда ИИ просто сп...</description><pubDate>Thu, 27 Nov 2025 09:01:11 GMT</pubDate><content:encoded>&lt;p&gt;Я думаю вы слышали об исследованиях, в которых выясняется, что ИИ на самом деле может не ускорять, а замедлять разработку? Но, как обычно, все концентрируются на времени, забывая, что у нас не только времени, но и &lt;a href=&quot;https://t.me/cherkashindev/394&quot;&gt;ума не хватает&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Иногда я работаю и время то у меня есть, но вот силы уже на исходе. И тогда ИИ просто спасает, ведь я могу простым языком объяснить что мне необходимо реализовать, потому что писать самому сил уже нет.&lt;/p&gt;
&lt;p&gt;Если подумать о продуктах, которые мы разрабатываем, то здесь аналогичная ситуация. ИИ может помочь как начинающим пользователям, так и пользователям, когда у них нет сил делать работу самим.&lt;/p&gt;
&lt;p&gt;У меня достаточно поверхностное представление, как ИИ интегрируется в продукт. На работе я реализовывал не очень сложные фичи с помощью ChatCompletion API, в теории понимаю что такое RAG, но на этом — всё.&lt;/p&gt;
&lt;p&gt;Разбираться самому нет ни сил, ни желания, поэтому я пошел по пути наименьшего сопротивления и нашёл для себя — &lt;a href=&quot;https://www.guidedao.xyz/ru&quot;&gt;Guide DAO&lt;/a&gt;. Это комьюнити по Web3 и AI, где дают нормальную программу и помогают не заблудиться по дороге.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Что понравилось&lt;/strong&gt;: активный Discord, постоянные стримы, можно в любой момент спросить и получить ответ от людей, которые уже варятся в теме. Плюс пожизненный доступ ко всем курсам.&lt;/p&gt;
&lt;p&gt;Но самое полезное — они помогают выйти на работу: хакерхаусы, разбор портфолио, мок-интервью. К концу обучения у тебя есть проекты и новые связи, а конкуренция в Web3 пока меньше, чем на классическом рынке.&lt;/p&gt;
&lt;p&gt;Недавно у них вышел курс по AI-агентам — это прям то, что мне нужно 🔥.&lt;/p&gt;
&lt;p&gt;С 24 по 30 ноября у них Чёрная пятница. По промокоду &lt;strong&gt;CHERKASHIN&lt;/strong&gt; — 25% + ещё 10% по ссылке на сайте, в сумме 35%. Есть и рассрочка.&lt;/p&gt;
&lt;p&gt;Если вам интересны Web3 или AI — можно глянуть подробности и бонусы в телеграм-боте: @&lt;strong&gt;GuideDAO_hallo_bot&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;А вы уже смотрите в сторону Web3 и ИИ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;⚡️ Пробую AI-агентов&lt;/li&gt;
&lt;li&gt;🧑‍💻 Изучаю Web3&lt;/li&gt;
&lt;li&gt;🙏 Хочу разобраться, но не знаю с чего начать&lt;/li&gt;
&lt;li&gt;💤 Пока просто крашу кнопки и перекладываю джейсоны&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-397-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-397-1.jpg"/></item><item><title>Конференции это не (только) про доклады</title><link>https://cherkashin.dev/posts/396/</link><guid isPermaLink="true">https://cherkashin.dev/posts/396/</guid><description>Конференции это не (только) про доклады

Раньше я ездил на конференции, чтобы слушать доклады.

Но, конференции это не только доклады, это живое общение с множеством единомышленников, которые могут поделиться своим опытом.

Когда я был на &quot;Я 💛 Фронтенд&quot;, я проводил огромное количество времени с яндексоидами, расспраши...</description><pubDate>Mon, 24 Nov 2025 09:01:01 GMT</pubDate><content:encoded>&lt;p&gt;**Конференции это не (только) про доклады
**
Раньше я ездил на конференции, чтобы слушать доклады.&lt;/p&gt;
&lt;p&gt;Но, конференции это не только доклады, это живое общение с множеством единомышленников, которые могут поделиться своим опытом.&lt;/p&gt;
&lt;p&gt;Когда я был на “Я 💛 Фронтенд”, я проводил огромное количество времени с яндексоидами, расспрашивая, как у них устроены процессы разработки и тестирования.&lt;/p&gt;
&lt;p&gt;А в последний раз, когда я был на AI Boost от команды Surf (спасибо &lt;a href=&quot;https://t.me/marketingandhorses&quot;&gt;Диане&lt;/a&gt; за приглашение), мой друг внезапно опоздал на поезд всего на пару минут 😅 — и у меня появилось целых 6 часов, чтобы заранее накидать список вопросов про использование ИИ, которые меня интересовали:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сколько вы тратите на каждого сотрудника, чтобы он мог пользоваться нейросетями?&lt;/li&gt;
&lt;li&gt;Как правильно использовать Мемори Банк?&lt;/li&gt;
&lt;li&gt;Какие языковые модели вы используете?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Но доклады на AI Boost тоже были очень интересными. Одна из главных мыслей, которую я вынес:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;💡 Я уже сижу полчаса и всё ещё не написал ни строчки кода.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Это страх почему многие избегают использовать ИИ. Мы часто не хотим продумывать решение и сразу бросаемся писать код. Также и с промптом, мы не хотим потратить даже 20 минут на написание хорошего промпта, ведь как так, прошло уже 20 минут, а я ещё ничего не написал 😳. Но эти 20 минут могут экономят часы реализации — ИИ ведь пишет код куда быстрее нас с вами.&lt;/p&gt;
&lt;p&gt;Ну и конференции, это конечно личные знакомства.&lt;/p&gt;
&lt;p&gt;Я давно подписан на &lt;a href=&quot;https://t.me/vibe_coding_channel&quot;&gt;Костю Чуйкова&lt;/a&gt;, а тут довелось познакомиться в оффлайне. Поговорили про использование ИИ, работу мою работу в Американской компании, ну и про ведение блога, конечно 😄.&lt;/p&gt;
&lt;p&gt;А для чего вы посещаете конференции?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🧑‍💻 Послушать доклады&lt;/li&gt;
&lt;li&gt;👍 Пообщаться&lt;/li&gt;
&lt;li&gt;❤️ И то, и другое&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#conference #about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-396-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-396-1.jpg"/></item><item><title>Необычный способ трудоустройства</title><link>https://cherkashin.dev/posts/395/</link><guid isPermaLink="true">https://cherkashin.dev/posts/395/</guid><description>Необычный способ трудоустройства

По-моему я читал о чём-то подобном  в книге Сомнеза &quot;Путь программиста&quot;, но сегодня хотел бы рассказать про случай, который произошел совершенно случайно.

Несколько лет назад я написал статью Интегрируем Яндекс Музыку в Visual Studio Code, где описал, как я техническую сторону разрабо...</description><pubDate>Mon, 17 Nov 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;**Необычный способ трудоустройства
**
По-моему я читал о чём-то подобном  в книге Сомнеза “Путь программиста”, но сегодня хотел бы рассказать про случай, который произошел совершенно случайно.&lt;/p&gt;
&lt;p&gt;Несколько лет назад я написал статью &lt;a href=&quot;https://habr.com/ru/articles/725460/&quot;&gt;Интегрируем Яндекс Музыку в Visual Studio Code&lt;/a&gt;, где описал, как я техническую сторону разработки расширения &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=acherkashin.yandex-music-extension&quot;&gt;YandexMusic&lt;/a&gt;.  Привет всем, кто подписались на меня после этой статьи 👋.&lt;/p&gt;
&lt;p&gt;Так вот после этого меня позвали на собеседование в Яндекс именно в команду Яндекс.Музыки 😅, и неожиданно, потому что я использовал Electron в своей реализации. А всё потому, что команда Яндекса начинала разработку кросс-платформенного приложения Яндекс.Музыки на Electron.&lt;/p&gt;
&lt;p&gt;После этого я начал готовиться пройти &lt;del&gt;все круги ада&lt;/del&gt; алгоритмические секции.
На первой секции были не сложные задания, но после рабочего дня, я знатно тупил, но смог решить несколько задачек.&lt;/p&gt;
&lt;p&gt;Потом я начал готовиться ко второму этапу, но тут вмешались санкции, мой банк отрубили от свифта, и вместо подготовки к собеседованию, я начал обзванивать банки, чтобы получить мои честно заработанные зелёные. Банк нашел, ушёл в отпуск и так и не вернулся ко второму этапу.&lt;/p&gt;
&lt;p&gt;Так я и упустил шанс попасть в команду Яндекс.Музыки, не знаю хорошо это или плохо, но опыт интересный 😅.&lt;/p&gt;
&lt;p&gt;А на фотке это меня пустили поработать в офисе Яндекса, а потому мы поехали на Big Tech Night.&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-395-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-395-1.jpg"/></item><item><title>Помните, как говорил Матроскин &quot;Средства у нас есть. У нас ума не хватает&quot;.</title><link>https://cherkashin.dev/posts/394/</link><guid isPermaLink="true">https://cherkashin.dev/posts/394/</guid><description>Помните, как говорил Матроскин &quot;Средства у нас есть. У нас ума не хватает&quot;.

Этот год выдался очень тяжелым:

я наконец-то получил права и сел за рульстал тимлидом и нагрузка резко возросла5 месяцев учился в стратопланеначинается подготовка к ремонту

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

Это я к тому,...</description><pubDate>Mon, 10 Nov 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;Помните, как говорил Матроскин “&lt;a href=&quot;https://www.youtube.com/watch?v=ACY2tm4Vpew&quot;&gt;Средства у нас есть. У нас ума не хватает&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;Этот год выдался очень тяжелым:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;я наконец-то получил права и сел за руль&lt;/li&gt;
&lt;li&gt;стал тимлидом и нагрузка резко возросла&lt;/li&gt;
&lt;li&gt;5 месяцев учился в стратоплане&lt;/li&gt;
&lt;li&gt;начинается подготовка к ремонту&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем год придётся заканчивать на морально волевых.&lt;/p&gt;
&lt;p&gt;Это я к тому, что важно следить не только за временем, но и за своей энергией. Иногда так устаёшь, что у меня нет даже сил прочитать входящие сообщения. Я сразу представляю, что сейчас завяжется диалог и его нужно будет продолжить, а сил у меня на это попросту нет. Поэтому откладываю его прочтение до тех пор пока “когда я буду готов”. Ну, конечно, тут смотря кто пишет.&lt;/p&gt;
&lt;p&gt;И уже некоторое время, я использую, как я его называю “путь наименьшего сопротивления”. Или точнее “делай то, от чего тебя не тошнит” 😄&lt;/p&gt;
&lt;p&gt;Всегда есть куча каких-то дел, которые делать, естественно, не хочется. Даже при одной мысли, что нужно ими заниматься начинается рвотный рефлекс. Но дел ведь много, так что вместо самого противного можно выбрать хоть что-то чуть более приятное.&lt;/p&gt;
&lt;p&gt;1️⃣ Например, вместо того чтобы думать, что мне уже нужно заказывать для ремонта, я занимаюсь демонтажом плинтусов 😄 — потому что это вызывает наименьшее отторжение и даёт ощущение, что процесс хоть как-то двигается.&lt;/p&gt;
&lt;p&gt;2️⃣ Или вмест обучения в Стратоплане, я выбираю компрессор для машины.&lt;/p&gt;
&lt;p&gt;Мне это помогает продолжать идти вперёд небольшими шагами и не выдохнуться.&lt;/p&gt;
&lt;p&gt;Поставьте ❤️ — пусть у меня будет ещё один источник энергии, кроме кофе и дедлайнов.&lt;/p&gt;
&lt;p&gt;#отдых&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-394-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-394-1.jpg"/></item><item><title>Впереди выходные — отличная возможность вспомнить, что жизнь не только про “саночки возить”, но и…</title><link>https://cherkashin.dev/posts/392/</link><guid isPermaLink="true">https://cherkashin.dev/posts/392/</guid><description>Впереди выходные — отличная возможность вспомнить, что жизнь не только про “саночки возить”, но и про то, чтобы &quot;покататься&quot;.

Не будьте как утка. Отдохните по-человечески.
Насладитесь результатами того, что уже сделали — вы это точно заработали.

Расскажите, как вы отдыхаете? 🙏

Ставь:

👍 — если регулярно отдыхаешь,...</description><pubDate>Mon, 03 Nov 2025 09:11:27 GMT</pubDate><content:encoded>&lt;p&gt;Впереди выходные — отличная возможность вспомнить, что жизнь не только про “саночки возить”, но и про то, чтобы “покататься”.&lt;/p&gt;
&lt;p&gt;Не будьте как утка. Отдохните по-человечески.
Насладитесь результатами того, что уже сделали — вы это точно заработали.&lt;/p&gt;
&lt;p&gt;Расскажите, как вы отдыхаете? 🙏&lt;/p&gt;
&lt;p&gt;Ставь:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👍 — если регулярно отдыхаешь, и не забываешься “кататься на саночках”&lt;/li&gt;
&lt;li&gt;😭 — если увидел в утке себя, и только и делаешь, что возишь саночки, а кататься некогда&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#отдых&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-393-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-393-1.jpg"/></item><item><title>💸 Валютная удалёнка в 2025</title><link>https://cherkashin.dev/posts/387/</link><guid isPermaLink="true">https://cherkashin.dev/posts/387/</guid><description>💸 Валютная удалёнка в 2025

Думаю, всем понятно, почему многие разработчики, находясь в России, работали на зарубежные компании: платят больше, чем в России, а цены ниже, чем за рубежом.

Всё, что для этого нужно было сделать, — открыть ИП, выбрать банк и ждать, пока на счёт не капнет кругленькая сумма.

В этом плане,...</description><pubDate>Mon, 27 Oct 2025 08:44:33 GMT</pubDate><content:encoded>&lt;p&gt;**💸 Валютная удалёнка в 2025
**
Думаю, всем понятно, почему многие разработчики, находясь в России, работали на зарубежные компании: платят больше, чем в России, а цены ниже, чем за рубежом.&lt;/p&gt;
&lt;p&gt;Всё, что для этого нужно было сделать, — открыть ИП, выбрать банк и ждать, пока на счёт не капнет кругленькая сумма.&lt;/p&gt;
&lt;p&gt;В этом плане, конечно, многое изменилось. Раньше перебирали харчами: у этого банка дорогое обслуживание, у этого долго проходит валютный контроль, а тут нет онлайн-бухгалтерии, а здесь интерфейс интернет-банка какой-то стрёмный. Помню, как я открывал новый счёт, сидя в Черногории — красота.&lt;/p&gt;
&lt;p&gt;Как это выглядит сейчас:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;идёт 2025 год&lt;/li&gt;
&lt;li&gt;выходит новый пакет санкций&lt;/li&gt;
&lt;li&gt;ты начинаешь смотреть свежий список банков, попавших под санкции&lt;/li&gt;
&lt;li&gt;в ужасе находишь там свой банк&lt;/li&gt;
&lt;li&gt;следующий месяц обзваниваешь все банки (раньше я и понятия не имел, сколько у нас в стране банков 😅), и у тебя всего три вопроса:
&lt;ul&gt;
&lt;li&gt;может ли ваш банк принять входящий перевод из страны Х?&lt;/li&gt;
&lt;li&gt;сколько стоит открытие счёта?&lt;/li&gt;
&lt;li&gt;сколько займёт открытие счёта?&lt;/li&gt;
&lt;li&gt;согласитесь, планка требований резко упала 😄&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;находишь банк в Ростове-на-Дону, который готов открыть тебе счёт. И тебе уже плевать, сколько стоит обслуживание, какой там курс конвертации и насколько говняный интерфейс. В ближайшие выходные ты уже едешь туда целые сутки, чтобы просто открыть счёт&lt;/li&gt;
&lt;li&gt;спустя три месяца всё повторяется&lt;/li&gt;
&lt;li&gt;теперь ты находишь региональный банк под Новосибирском. Он не под санкциями, ты «на радостях» уже готов лететь в холодную Сибирь… Но, к сожалению, банк не может принимать входящие платежи в валюте из страны Х&lt;/li&gt;
&lt;li&gt;начинаешь разбираться, как открыть счёт за границей, регистрируешься на платных форумах, чтобы поговорить с теми, у кого это получилось&lt;/li&gt;
&lt;li&gt;думаешь: «Да пошло оно всё к чёрту, пойду искать новую работу»&lt;/li&gt;
&lt;li&gt;но тут находишь альтернативный способ оплаты — без лишних заморочек, с уровнем сервиса, который я описал в начале. Теперь ты снова можешь воротить носом и смотреть на качество интерфейса, поддержки, на стоимость обслуживания и т. д., но к этому добавляется ещё один критерий — комиссия за валютные переводы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Последний такой поиск нового способа входящих платежей занял три месяца. Было, конечно, не очень комфортно. Поэтому если раз в сто лет увидите рекламу в канале — не спешите доставать какашки: возможно, я снова сижу без зарплаты, а за Claude платить как-то надо 😄.&lt;/p&gt;
&lt;p&gt;В общем, если вы думаете, что баксы из-за рубежа получить невозможно — это совсем не так. Хотя, конечно, желающих отправить их вам стало заметно меньше.&lt;/p&gt;
&lt;p&gt;Если будут вопросы про валютную удалёнку — обязательно пишите 🙏.&lt;br&gt;
А на фотках — декабрьский Ростов, куда мы действительно ездили из Курска открывать счета в конце прошлого года.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;А у вас есть опыт валютной удалёнки?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💸 Было дело
💤 Неа, ещё не довелось
👀 В активном поиске&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-387-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-387-1.jpg"/></item><item><title>🚀 Лидерство в команде</title><link>https://cherkashin.dev/posts/385/</link><guid isPermaLink="true">https://cherkashin.dev/posts/385/</guid><description>🚀 Лидерство в команде

В прошлом месяце закончился последний модуль обучения в Стратоплане. После него я наконец смог немного выдохнуть — год выдался насыщенным. Но сегодня не об этом. Этот модуль был посвящён лидерству в команде.

🧭 Теории лидерства

В целом:

Лидер — это тот, кто берёт ответственность за результат ...</description><pubDate>Wed, 22 Oct 2025 09:01:02 GMT</pubDate><content:encoded>&lt;p&gt;🚀 &lt;strong&gt;Лидерство в команде&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В прошлом месяце закончился последний модуль &lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;обучения в Стратоплане&lt;/a&gt;. После него я наконец смог немного выдохнуть — год выдался насыщенным. Но сегодня не об этом. Этот модуль был посвящён лидерству в команде.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🧭 Теории лидерства&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В целом:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Лидер — это тот, кто берёт ответственность за результат команды и выстраивает её работу так, чтобы все шли к общей цели.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Но все лидеры разные, и каждый «затаскивает» свою роль за счёт разных качеств.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Кто-то — благодаря врождённым особенностям: уверенности, энергии, уму и знанию дела.&lt;/li&gt;
&lt;li&gt;Кто-то вдохновляет поведением — проводит встречи, делает заметки, ничего не забывает и всегда доводит дела до конца.&lt;/li&gt;
&lt;li&gt;А кто-то просто не боится брать на себя ответственность — например, общается с заказчиком, когда остальные предпочитают отмалчиваться.&lt;/li&gt;
&lt;li&gt;Есть и такие, кто не самый харизматичный, но зато чётко понимает, как устроена команда и какая у него в ней роль.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если попробовать соотнести это с теориями, то всё это — &lt;strong&gt;личностное, поведенческое, ситуационное и организационно-ролевое лидерство&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;А чтобы команда шла туда, куда нужно, лидеру важно &lt;strong&gt;правильно расставлять приоритеты&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;⚖️ Приоритеты&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Все знают пример с банкой, в которую сначала кладут большие камни, потом поменьше, потом песок и заливают водой.&lt;/p&gt;
&lt;p&gt;Так вот, для приоритезации этот пример прекрасно подходит:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🪨 &lt;strong&gt;Большие камни&lt;/strong&gt; — глобальные цели, то, ради чего вообще всё.&lt;/li&gt;
&lt;li&gt;🪨 Камни поменьше — важные, но не стратегические дела.&lt;/li&gt;
&lt;li&gt;🏖️ Песок — рутина, повседневные мелочи.&lt;/li&gt;
&lt;li&gt;🍺 И да, место для кружки пива с друзьями тоже должно остаться.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Именно в такой последовательности. Не сыпем песок, а потом пытаемся впихнуть камни — иначе то, что действительно важно, не поместится.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;На практике у нас был классный кейс: нужно было приоритизировать задачи руководителя в &lt;strong&gt;катастрофичный день&lt;/strong&gt; —&lt;br&gt;
сотрудники увольняются, зубы болят, ребёнка забрать из сада некому, сгорает бесплатный урок английского от работодателя и куча других дел.&lt;/p&gt;
&lt;p&gt;Так вот, то, как приоритизировали мы, совсем не совпало с тем, как это сделала команда из Индии.&lt;br&gt;
Они поставили на первое место английский и объяснили это просто:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«В долгосрочной перспективе то, что ребёнка заберут позже из сада — не беда.&lt;br&gt;
Беда, если через 10 лет не сможешь оплатить ему обучение».&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Я часто забываю остановиться и подумать, что действительно важно. Когда бегаешь, как белка в колесе, ничего не видишь, кроме этого колеса. А ведь на самом деле дверь в клетке может быть открыта. А может, и клетки вовсе нет.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🛠️ Инструменты приоритизации&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Чтобы не тонуть в потоке задач, полезно структурировать приоритеты.&lt;br&gt;
На курсе мы разбирали несколько инструментов — вот те, которые действительно работают.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🟦 Матрица Эйзенхауэра&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Классика. Делим задачи по двум признакам: &lt;strong&gt;срочность&lt;/strong&gt; и &lt;strong&gt;важность&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Срочные и важные — делай сразу.&lt;/li&gt;
&lt;li&gt;Срочные, но не важные — делегируй.&lt;/li&gt;
&lt;li&gt;Важные, но не срочные — планируй.&lt;/li&gt;
&lt;li&gt;Ни срочные, ни важные — забудь.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Главное — не попасть в ловушку «всё срочно». Настоящих срочных дел всегда немного — всё остальное просто неорганизованно.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🟨 Метод ABC&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Каждой задаче присваивается буква:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt; — критически важные (если не сделать — будут серьёзные последствия).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;B&lt;/strong&gt; — важные, но не критичные.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C&lt;/strong&gt; — мелочи, которые можно делать в свободное время.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Когда всё в списке «A» — это сигнал, что нужно пересмотреть фокус.&lt;/p&gt;
&lt;p&gt;📝 &lt;strong&gt;Отзыв&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Этот модуль меня довольно сильно зацепил.
Я привык всё делать на совесть и с полной отдачей, но часто засиживаюсь и не хватает времени на личные дела.&lt;/p&gt;
&lt;p&gt;Из модуля вынес один полезный вопрос:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«А что будет, если я не сделаю эту задачу?»&lt;br&gt;
Если ответ — «ничего», то, возможно, эта задача не стоит ваших нервов.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Вас не уволят, если задача закроется на день позже.&lt;/li&gt;
&lt;li&gt;А вот если постоянно пропускать тренировки, мечта о форме останется мечтой.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем, у меня было ощущение, будто сходил к психологу — смог выбраться из колеса и задуматься о том, &lt;strong&gt;что для меня действительно важно&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Ставь:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;😎 — если умеешь расставлять приоритеты&lt;/li&gt;
&lt;li&gt;😭 — если пока крутишься как белка в колесе&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-385-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-385-1.jpg"/></item><item><title>Когда работаешь в международной компании — есть один огромный плюс:</title><link>https://cherkashin.dev/posts/384/</link><guid isPermaLink="true">https://cherkashin.dev/posts/384/</guid><description>Когда работаешь в международной компании — есть один огромный плюс:
в каждой стране свои национальные праздники.

Коллеги из Индии всю неделю отмечают Дивали — праздник победы добра над злом.
А это значит, что никаких:

давай быстро созвонимся на 5 минутпосмотри мой пул реквестсколько примерно займёт вот эта задача?вы ...</description><pubDate>Mon, 20 Oct 2025 09:31:18 GMT</pubDate><content:encoded>&lt;p&gt;Когда работаешь в международной компании — есть один огромный плюс:
в каждой стране свои национальные праздники.&lt;/p&gt;
&lt;p&gt;Коллеги из Индии всю неделю отмечают Дивали — праздник победы добра над злом.
А это значит, что никаких:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;давай быстро созвонимся на 5 минут&lt;/li&gt;
&lt;li&gt;посмотри мой пул реквест&lt;/li&gt;
&lt;li&gt;сколько примерно займёт вот эта задача?&lt;/li&gt;
&lt;li&gt;вы опять тесты поломали?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А с Америкой пересечение — всего пара рабочих часов: пока они проснутся и выпьют свой кофе, я уже закончу работать.&lt;/p&gt;
&lt;p&gt;В общем, прогноз на неделю:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🌧️ За окном: начало рабочей недели&lt;/li&gt;
&lt;li&gt;🏖️ Ощущается: как начало отпуска&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded></item><item><title>Мне кажется, за время работы, я достаточно насмотрелся на говнокод (да и сам его написал не мало,…</title><link>https://cherkashin.dev/posts/383/</link><guid isPermaLink="true">https://cherkashin.dev/posts/383/</guid><description>Мне кажется, за время работы, я достаточно насмотрелся на говнокод ||(да и сам его написал не мало, чего уж там 😅)||. И когда общаешься с авторами такого кода, их позиция такова: &quot;Ну код же рабочий?! Ну да, я пишу вот так, а ты — по-другому. Мы не одинаковы&quot;.

И не поспоришь, правда работает 🤷‍♂️. Руководству тоже по...</description><pubDate>Mon, 13 Oct 2025 10:03:05 GMT</pubDate><content:encoded>&lt;p&gt;Мне кажется, за время работы, я достаточно насмотрелся на говнокод ||(да и сам его написал не мало, чего уж там 😅)||. И когда общаешься с авторами такого кода, их позиция такова: “Ну код же рабочий?! Ну да, я пишу вот так, а ты — по-другому. Мы не одинаковы”.&lt;/p&gt;
&lt;p&gt;И не поспоришь, правда работает 🤷‍♂️. Руководству тоже пофиг как там код написан, нужно фичи релизить, а не вот это всё. И когда-то давно мне пришла в голову такая аналогия.&lt;/p&gt;
&lt;p&gt;Давайте представим, что вы читаете книгу. В одной главе текст идёт мелким шрифтом, в другой — крупным. Где-то абзацы разделены двойным интервалом, а где-то слова слиты без пробелов. В одной главе автор использует подчёркивания для выделения важных мыслей, а в другой — жирный шрифт или вовсе ничего.&lt;/p&gt;
&lt;p&gt;Теперь добавим ещё больше хаоса. Представьте, что эта книга вообще не разделена на главы или абзацы — просто сплошной текст на тысячи строк. Или что один и тот же термин в книге обозначается то одним словом, то другим, а иногда и вовсе непонятными сокращениями. Сможете ли вы нормально читать такую книгу?  Или просто закроете её от раздражения?&lt;/p&gt;
&lt;p&gt;Так вот, говнокод — это именно такая книга. Каждый, кто откроет этот код, будет теряться, и даже вы сами через месяц будете сидеть над ним и думать: «Кто это написал? И что это значит?». Была у меня ситуация, когда коллега воскликнул: “Кто вообще это написал?!”, а потом сделал &lt;code&gt;git blame&lt;/code&gt; и вышел сам на себя 😄.&lt;/p&gt;
&lt;p&gt;В общем, пишите код так, чтобы его было просто читать, насколько это возможно. Ваши коллеги (и вы сами в будущем) скажут вам за это спасибо.&lt;/p&gt;
&lt;p&gt;А вот кстати интересная статья на хабре, в тему.&lt;br&gt;
&lt;a href=&quot;https://habr.com/ru/articles/302570/&quot;&gt;Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;А вы как относитесь к чистоте кода?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔥 Читаемый код наше всё&lt;/li&gt;
&lt;li&gt;🤷‍♂️ Главное, чтобы работало&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-383-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-383-1.jpg"/></item><item><title>Я всё думал, что же мне не нравится в Obsidian. С тех пор как я перешёл из Notion, постоянно было…</title><link>https://cherkashin.dev/posts/380/</link><guid isPermaLink="true">https://cherkashin.dev/posts/380/</guid><description>Я всё думал, что же мне не нравится в Obsidian. С тех пор как я перешёл из Notion, постоянно было ощущение, что что-то не так.

И я понял, что дело просто во внешнем виде: банально нет иконок, непонятно, где файл, а где папка.

Пока что установил тему Obsidian Border. Там ещё есть куча кастомизаций через плагин obsidia...</description><pubDate>Mon, 06 Oct 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;Я всё думал, что же мне не нравится в Obsidian. С тех пор как я перешёл из Notion, постоянно было ощущение, что что-то не так.&lt;/p&gt;
&lt;p&gt;И я понял, что дело просто во внешнем виде: банально нет иконок, непонятно, где файл, а где папка.&lt;/p&gt;
&lt;p&gt;Пока что установил тему &lt;a href=&quot;https://github.com/Akifyss/obsidian-border&quot;&gt;Obsidian Border&lt;/a&gt;. Там ещё есть куча кастомизаций через плагин &lt;a href=&quot;https://github.com/mgmeyers/obsidian-style-settings&quot;&gt;obsidian-style-settings&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Собственно вот до и после.&lt;/p&gt;
&lt;p&gt;А вы какими темами пользуетесь? 🤔&lt;/p&gt;
&lt;p&gt;#obsidian&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-380-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-380-1.jpg"/></item><item><title>Когда мы обновили pnpm с 7-й до 10-й версии, оказалось, что формат файла pnpm.lock изменился — и…</title><link>https://cherkashin.dev/posts/378/</link><guid isPermaLink="true">https://cherkashin.dev/posts/378/</guid><description>Когда мы обновили pnpm с 7-й до 10-й версии, оказалось, что формат файла pnpm.lock изменился — и версии пакетов немного поехали. В итоге на CI начали рандомно падать некоторые асинхронные jest-тесты. Локально же всё работало без проблем.

Падали примерно одни и те же тесты, но разобраться, из-за чего именно и как это с...</description><pubDate>Wed, 01 Oct 2025 09:01:00 GMT</pubDate><content:encoded>&lt;p&gt;Когда мы обновили pnpm с 7-й до 10-й версии, оказалось, что формат файла &lt;code&gt;pnpm.lock&lt;/code&gt; изменился — и версии пакетов немного поехали. В итоге на CI начали рандомно падать некоторые асинхронные jest-тесты. Локально же всё работало без проблем.&lt;/p&gt;
&lt;p&gt;Падали примерно одни и те же тесты, но разобраться, из-за чего именно и как это связано с обновлением пакетов, так и не удалось.&lt;/p&gt;
&lt;p&gt;Что попробовали:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Проверили, что в &lt;code&gt;pnpm.lock&lt;/code&gt; нет нескольких разных версий jest&lt;/li&gt;
&lt;li&gt;Обновили jest до свежей версии&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Результат — без изменений.&lt;/p&gt;
&lt;p&gt;В итоге, времени копаться глубже уже не было, поэтому к проблемным тестам добавили:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;jest.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;retryTimes&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// повторяет тест до 3 раз, если он упал&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Для вас решение 👍 норм или 🤔 стрём?&lt;/p&gt;
&lt;p&gt;#jest #testing #frontend&lt;/p&gt;</content:encoded></item><item><title>Игрался вчера с AI тулзами для генерации дизайна:</title><link>https://cherkashin.dev/posts/372/</link><guid isPermaLink="true">https://cherkashin.dev/posts/372/</guid><description>Игрался вчера с AI тулзами для генерации дизайна:

https://uxpilot.ai/  — получаются неплохие дизайны с хорошей детализациейhttps://stitch.withgoogle.com/ — так себе

С генерацией лендосов справляются очень неплохо. С UI для no-code плаформ тоже, с UI для карт на троечку.
В целом для прототипипрвания — очень даже ничег...</description><pubDate>Fri, 26 Sep 2025 10:02:01 GMT</pubDate><content:encoded>&lt;p&gt;Игрался вчера с AI тулзами для генерации дизайна:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://uxpilot.ai/&quot;&gt;https://uxpilot.ai/&lt;/a&gt;  — получаются неплохие дизайны с хорошей детализацией&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stitch.withgoogle.com/&quot;&gt;https://stitch.withgoogle.com/&lt;/a&gt; — так себе&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;С генерацией лендосов справляются очень неплохо. С UI для no-code плаформ тоже, с UI для карт на троечку.
В целом для прототипипрвания — очень даже ничего.&lt;/p&gt;
&lt;p&gt;Расскажите, какими AI тулзами вы пользуетесь? 🙏&lt;/p&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-372-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-372-1.jpg"/></item><item><title>Я не менял работу уже 8 лет и недавно решил посмотреть какие сейчас зарплаты предлагают на рынке.…</title><link>https://cherkashin.dev/posts/370/</link><guid isPermaLink="true">https://cherkashin.dev/posts/370/</guid><description>Я не менял работу уже 8 лет и недавно решил посмотреть какие сейчас зарплаты предлагают на рынке. Поспрашивал знакомых и вот какие ресурсы мне посоветовали:

GetMatchХабр Карьера

Может подкините ещё какие-то ресурсы?</description><pubDate>Mon, 22 Sep 2025 10:12:01 GMT</pubDate><content:encoded>&lt;p&gt;Я не менял работу уже 8 лет и недавно решил посмотреть какие сейчас зарплаты предлагают на рынке. Поспрашивал знакомых и вот какие ресурсы мне посоветовали:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://getmatch.ru/salaries/js_frontend?se=lead&amp;#x26;wf=remote&quot;&gt;GetMatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://career.habr.com/salaries&quot;&gt;Хабр Карьера&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Может подкините ещё какие-то ресурсы?&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-370-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-370-1.jpg"/></item><item><title>Чуть не забыл поделиться шаблоном ведения заметок для 1:1 и примером проведения развивающего 1:1</title><link>https://cherkashin.dev/posts/368/</link><guid isPermaLink="true">https://cherkashin.dev/posts/368/</guid><description>Чуть не забыл поделиться шаблоном ведения заметок для 1:1 и примером проведения развивающего 1:1</description><pubDate>Fri, 19 Sep 2025 13:13:41 GMT</pubDate><content:encoded>&lt;p&gt;Чуть не забыл поделиться шаблоном ведения заметок для 1:1 и примером проведения развивающего 1:1&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-368-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-368-1.jpg"/></item><item><title>Вспомните свой последний 1:1 с руководителем. Был ли он для вас полезен?</title><link>https://cherkashin.dev/posts/367/</link><guid isPermaLink="true">https://cherkashin.dev/posts/367/</guid><description>Вспомните свой последний 1:1 с руководителем. Был ли он для вас полезен?

Или ваши 1:1 выглядят скорее как формальность и превращаются в обсуждение статуса задач, во время которых ваш руководитель постоянно переписывается с другими людьми.

Или же, вам не хватает доверия к руководителю, чтобы рассказать всё что у вас н...</description><pubDate>Wed, 17 Sep 2025 09:36:33 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Вспомните свой последний 1:1 с руководителем. Был ли он для вас полезен?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Или ваши 1:1 выглядят скорее как формальность и превращаются в обсуждение статуса задач, во время которых ваш руководитель постоянно переписывается с другими людьми.&lt;/p&gt;
&lt;p&gt;Или же, вам не хватает доверия к руководителю, чтобы рассказать всё что у вас накипело? И в итоге вы уходите со встречи с мыслью “только время потратил, лучше бы таску закрыл”.&lt;/p&gt;
&lt;p&gt;Как вы могли догадаться, сегодня будет отзыв по &lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;4-му модулю в Стратоплане&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Зачем ❓&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Представьте: ваш конь говорит — «слушай, надоело прыгать буквой Г, хочу ходить наискосок. А у Серёги на соседней доске проект поинтереснее, ещё два хода сделаю — и уйду туда».&lt;/p&gt;
&lt;p&gt;Чтобы такие разговоры не звучали “как гром среди ясного неба”, руководителю важно понимать проблемы и мотивацию сотрудников. А большинство об этом не расскажут — если не спросить прямо.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🪨 База&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1:1 не реже раза в 2 недели, иначе ожидания и реальность сильно разойдутся&lt;/li&gt;
&lt;li&gt;Фокусируемся на человеке, а не на задачах&lt;/li&gt;
&lt;li&gt;Обсуждаем, что хорошего и плохого произошло с последней встречи. Что сделать чтобы плохое происходило реже&lt;/li&gt;
&lt;li&gt;Фиксируем договорённости&lt;/li&gt;
&lt;li&gt;Обмениваемся обратной связью&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🦻 &lt;strong&gt;Метод активного слушания — слушать больше чем говорить&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда с вами делятся проблемой, вы спешите как можно скорее предложить решение или стараетесь копнуть глубже?&lt;/p&gt;
&lt;p&gt;Вообще это мега навык, задать вопрос и молчать, позволив человеку выговориться.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Задали вопрос — молчите, кивайте, не перебивайте.&lt;/li&gt;
&lt;li&gt;Человек закончил — сделайте паузу.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Зачастую, если поспешить предложить решение проблемы — легко можно что-то упустить и в итоге получится, что вы предлагаете решение даже не по верхушке айсберга, а видя лишь отражение айсберга в зеркале. Если ты задашь ещё 5 вопросов, то скорее всего окажется, что проблема совсем в другом.&lt;/p&gt;
&lt;p&gt;🎯 &lt;strong&gt;Виды 1:1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Вроде это очевидная мысль, но для меня это была самая главная мысль, которую я вынес из модуля: “Бывают разные виды встреч 1:1, и у каждого — свои цели”.&lt;/p&gt;
&lt;p&gt;Не хватит места расписать всё подробно, поэтому коротко пробегусь по каждому типу:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Синхронизация — Обсуждаем, одинаково ли мы понимаем:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;насколько хороши результаты,&lt;/li&gt;
&lt;li&gt;какие цели и зачем, а как они связаны с целями человека,&lt;/li&gt;
&lt;li&gt;что продолжать делать, что начать делать иначе&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Мотивационный — здесь нам нужно понять, какие “дыры” забирают силы у сотрудника, и какие есть “опоры”, из которых можно черпать силы. Наша задача — увеличить количество опор, и закрыть “дыры” или научиться с ними жить так, чтобы они не мешали работать.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Развивающий — тут всё понятно, определяем что человек уже умеет, чему нужно научиться и главное, как это применить в работе.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Корректирующий — обсуждаем, что надо перестать делать или делать иначе. Даём обратную связь по методам SBI и BOFF.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;У тех, кто ходит в офис может появиться логичный вопрос: &lt;strong&gt;Зачем проводить 1:1 если мы итак постоянно видимся? 🤷‍♂️&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Но давайте честно, когда у вас была возможность непрерывно говорить и задавать волнующие вас вопросы в течении 40 минут в располагающей для этого обстановке?&lt;/p&gt;
&lt;p&gt;📝 &lt;strong&gt;Отзыв&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Модуль оказался простым и сложным одновременно. Сначала казалось, что говорим о банальных вещах — теория минимальна, всё вроде понятно. Но на второй день стало ясно, что потребуется много времени, чтобы начать проводить встречи правильно.&lt;/li&gt;
&lt;li&gt;Также неожиданно модуль помог понять, что не стоит требовать бурного роста от сотрудников, можно идти и маленькими шагами.&lt;/li&gt;
&lt;li&gt;Фишка, которую уже тестирую — создаю документ для каждого сотрудника для 1:1, где фиксирую заметки и договорённости.&lt;/li&gt;
&lt;li&gt;Узнал синоним слову “жопоголизм” — “нытинг” 😄&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ставьте&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👍 — если вы довольны своим 1:1&lt;/li&gt;
&lt;li&gt;😢 — если нет&lt;/li&gt;
&lt;li&gt;😱 — если у вас вообще нет 1:1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;||P.S. Стратоплану исполнилось 15 лет, и в честь этого до 21 сентября можно урвать скидку 30% на обучение по промокоду 🎟️ Friends30. В общем, если давно думали пройти обучение, есть шанс очень сильно сэкономить.||&lt;/p&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-367-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-367-1.jpg"/></item><item><title>✨ Функция attr() в CSS</title><link>https://cherkashin.dev/posts/366/</link><guid isPermaLink="true">https://cherkashin.dev/posts/366/</guid><description>✨ Функция attr() в CSS

После предыдущего поста про современный CSS, я вспомнил, что несколько месяцев назад применил CSS-функцию attr() в реализации JsonViewer с виртуальной прокруткой.

attr() позволяет взять значение любого HTML-атрибута и использовать его в стилях. Долгое время attr можно было применять только для ...</description><pubDate>Wed, 10 Sep 2025 08:46:48 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;✨ Функция attr() в CSS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;После &lt;a href=&quot;https://t.me/cherkashindev/350&quot;&gt;предыдущего поста&lt;/a&gt; про современный CSS, я вспомнил, что несколько месяцев назад применил CSS-функцию attr() в реализации &lt;a href=&quot;https://t.me/cherkashindev/333&quot;&gt;JsonViewer с виртуальной прокруткой.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;attr() позволяет взять значение любого HTML-атрибута и использовать его в стилях. Долгое время &lt;code&gt;attr&lt;/code&gt; можно было применять только для свойства content. Сейчас же attr() можно применять для любых свойств, но поддержка пока всего &lt;a href=&quot;https://caniuse.com/?search=attr&quot;&gt;~67% браузеров.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Чтобы реализовать дерево с виртуальной прокруткой нужно избавиться от вложенности дочерних узлов и отображать всё простым списком. А чтобы JsonViewer выглядел деревом — нужно добавить отступы в зависимости от вложенности свойства nesting-level * padding.&lt;/p&gt;
&lt;p&gt;💡 И тут можно применить attr:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.json-viewer__node&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  padding-left&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;calc&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;attr&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;data-level&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; type(&amp;#x3C;number&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)) * &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Node&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;level&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; className&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;json-viewer__node&quot;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; data-level&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;level&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      {&lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;/* ... */&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;👉 Тут мы указали, что для свойства padding-left хотим использовать значение атрибута data-level. При этом уточнили, что это не просто строка, а число &lt;code&gt;type(&amp;#x3C;number&gt;&lt;/code&gt;), чтобы CSS мог правильно умножить его на 20px и посчитать итоговый отступ.&lt;/p&gt;
&lt;p&gt;Конечно, отступы можно задать и просто через JSX, но мне в любом случае был нужен data-level атрибут, чтобы стилизовать узлы в зависимости от их уровня.&lt;/p&gt;
&lt;p&gt;📎 Ещё один пример применения функции attr() нашел в &lt;a href=&quot;https://doka.guide/css/attr/&quot;&gt;доке.&lt;/a&gt;
Тут мы отображаем ссылки в печатной версии страницы с помощью псевдоэлемента ::after.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; Подробнее о скидках и акциях можно узнать &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; href&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;http://best-site.ru/sales&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;по ссылке&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;@media&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; print&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;  a&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;::after&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    content&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot; [&quot;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; attr&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;href&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;]&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;@cherkashindev
#css&lt;/p&gt;</content:encoded></item><item><title>Надеюсь, все уже перевернули календарь 🗓️, и теперь снова можно поговорить про AI.</title><link>https://cherkashin.dev/posts/364/</link><guid isPermaLink="true">https://cherkashin.dev/posts/364/</guid><description>Надеюсь, все уже перевернули календарь 🗓️, и теперь снова можно поговорить про AI.

Все вокруг только и говорят о том, как они используют AI для разработки, но как интегрировать AI в продукт?

Ещё недавно для этого использовался JSON Mode. Для этого было достаточно указать:

{ &quot;type&quot;: &quot;jsonobject&quot; }И в системном промп...</description><pubDate>Fri, 05 Sep 2025 06:44:25 GMT</pubDate><content:encoded>&lt;p&gt;Надеюсь, все уже перевернули календарь 🗓️, и теперь снова можно поговорить про AI.&lt;/p&gt;
&lt;p&gt;Все вокруг только и говорят о том, как они используют AI для разработки, но как интегрировать AI в продукт?&lt;/p&gt;
&lt;p&gt;Ещё недавно для этого использовался &lt;a href=&quot;https://platform.openai.com/docs/guides/structured-outputs?lang=javascript&amp;#x26;utm_source=chatgpt.com#json-mode&quot;&gt;JSON Mode&lt;/a&gt;. Для этого было достаточно указать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{ &quot;type&quot;: &quot;json_object&quot; }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;И в системном промпте указать, что модель должна вернуть JSON.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Но JSON Mode гарантирует лишь то, что модель вернёт валидный JSON, при этом далеко не факт, что он будет соответствовать JSON-схеме, которая нужна вам.&lt;/p&gt;
&lt;p&gt;Эту проблему решает более современный подход — &lt;a href=&quot;https://platform.openai.com/docs/guides/structured-outputs?lang=javascript&quot;&gt;Structured Output&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Structured Output позволяет задать схему данных, и модель обязана вернуть результат, который ей соответствует. То есть мы получаем не “похоже на JSON”, а чётко определённую структуру.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; OpenAI &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;openai&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; client&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; OpenAI&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;({ apiKey: process.env.&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; response&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; client.chat.completions.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  model: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;gpt-4.1&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  messages: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { role: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, content: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Ты ассистент, который советует фильмы.&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { role: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, content: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Подскажи хороший фильм для пятничного вечера.&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  response_format: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    type: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;json_schema&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    json_schema: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      name: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;movie_suggestion&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      schema: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        type: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        properties: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          title: { type: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          genre: { type: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          year: { type: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        required: [&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;genre&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;year&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(response.choices[&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;].message.parsed);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Что здесь происходит:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Системный промпт&lt;/strong&gt; задаёт роль модели: она должна советовать фильмы.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;json_schema&lt;/strong&gt; описывает структуру ответа: объект с тремя обязательными полями — &lt;code&gt;title&lt;/code&gt; (строка), &lt;code&gt;genre&lt;/code&gt; (строка), &lt;code&gt;year&lt;/code&gt; (число).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В итоге при любом запросе на тему фильмов модель вернёт именно такой объект, и его можно использовать в коде — например, выводить в UI или сохранять в базу.
Но &lt;a href=&quot;https://platform.openai.com/docs/guides/structured-outputs?lang=javascript#how-to-use&quot;&gt;обработку пограничных случаев&lt;/a&gt; в любом случае добавить стоит.&lt;/p&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://ai.google.dev/gemini-api/docs/structured-output&quot;&gt;Gemini API — Structured output&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/structured-outputs&quot;&gt;Azure Foundry — Structured outputs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;А вы интегрируете AI в свои продукты?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;😎 конечно&lt;/li&gt;
&lt;li&gt;👀 пока нет, присматриваемся&lt;/li&gt;
&lt;li&gt;😈 выпиливаем&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;@cherkashindev
#ai&lt;/p&gt;</content:encoded></item><item><title>Я тут понял, что совсем не помню свои маршруты в отпуске: куда мы с женой ходили на завтрак, где…</title><link>https://cherkashin.dev/posts/354/</link><guid isPermaLink="true">https://cherkashin.dev/posts/354/</guid><description>Я тут понял, что совсем не помню свои маршруты в отпуске: куда мы с женой ходили на завтрак, где гуляли, какие экскурсии посещали. Поэтому быть этому каналу дневником памяти. Делюсь нашим питерским маршрутом:

День 1

🌯 Приезжаем и идём перекусить местной шаурмой шавермой в Vлаvaше.

Заселяемся в апартаменты Сердце Пе...</description><pubDate>Sun, 31 Aug 2025 09:02:15 GMT</pubDate><content:encoded>&lt;p&gt;Я тут понял, что совсем не помню свои маршруты в отпуске: куда мы с женой ходили на завтрак, где гуляли, какие экскурсии посещали. Поэтому быть этому каналу дневником памяти. Делюсь нашим питерским маршрутом:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;День 1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🌯 Приезжаем и идём перекусить местной &lt;del&gt;шаурмой&lt;/del&gt; шавермой в &lt;a href=&quot;https://yandex.ru/maps/-/CLEFrEPo&quot;&gt;Vлаvaше&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Заселяемся в апартаменты &lt;a href=&quot;https://yandex.ru/maps/org/serdtse_peterburga/166751082602?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Сердце Петербурга&lt;/a&gt; и отдыхаем после 15-часового поезда из Курска. Потом едем на &lt;a href=&quot;https://yandex.ru/maps/org/ostrov_novaya_gollandiya/199688219277?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;остров Новая Голландия&lt;/a&gt;, гуляем по территории и заходим в &lt;a href=&quot;https://yandex.ru/maps/org/kuznyahouse/1728919510?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Kuznyahouse&lt;/a&gt;, где берём кебаб из кролика и Пожарскую котлету.&lt;/p&gt;
&lt;p&gt;🌅 Чтобы утрясти всё съеденное, гуляем по &lt;a href=&quot;https://yandex.ru/maps/2/saint-petersburg/geo/galernaya_ulitsa/8017943/?ll=30.293015%2C59.932976&amp;#x26;z=16&quot;&gt;Галерной улице&lt;/a&gt; (||отличное название для офисов ИТ-компаний|| 😄) и затем сворачиваем на Адмиралтейскую набережную. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;День 2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🍳 Завтракаем в &lt;a href=&quot;https://yandex.ru/maps/org/joli_grand_bistrot/224542522414?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Joli Grand Bistrot&lt;/a&gt;. Заказываем шакшуку, она здесь кстати была такая же вкусная как, когда-то я пробовал в Тель-Авиве. &lt;/p&gt;
&lt;p&gt;Теперь едем в &lt;a href=&quot;https://yusupov-palace.ru/ru/programs/1&quot;&gt;Юсуповский дворец&lt;/a&gt; и “внимательно” (нет) слушаем самую нудную экскурсию в моей жизни. Хуже была только ночная прогулка по Неве несколько лет назад, где мы с женой просто уснули.&lt;/p&gt;
&lt;p&gt;🍲 Теперь идем в &lt;a href=&quot;https://yandex.ru/maps/org/aster/43110780638?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Aster&lt;/a&gt;. Здесь обязательно берем шикарный хлеб с копченым маслом, эфиопский фильтр кофе или капучино и морковный кекс.&lt;/p&gt;
&lt;p&gt;Потом — много гуляем в &lt;a href=&quot;https://yandex.ru/maps/org/letniy_sad/1021396158/?ll=30.335097,59.944580&amp;#x26;utm_source=share&amp;#x26;z=16&quot;&gt;Летнем саду&lt;/a&gt;, фоткаемся на &lt;a href=&quot;https://yandex.ru/maps/org/ermitazhny_most/119630987298?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Эрмитажном мосту&lt;/a&gt;, уворачиваемся от уличных фотографов на Дворцовой площади, и идём к &lt;a href=&quot;https://yandex.ru/maps/-/CLEJmHIW&quot;&gt;Спасу на Крови&lt;/a&gt; и в Михайловскому парку.&lt;/p&gt;
&lt;p&gt;🍷 Нагулявшись, не едем в &lt;a href=&quot;https://yandex.ru/maps/-/CLEFuZ35&quot;&gt;Trappist&lt;/a&gt; потому что мой внутренний алкоголик не готов отдать косарь за 0.5 пива. Лучше заехать в &lt;a href=&quot;https://yandex.ru/maps/org/khorovod/85813194898?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Хоровод&lt;/a&gt; и устроить себе Русское застолье: сет настоек (фруктовые — супер, овощные — ни о чём), окрошку, селедочку, грудинку горячего копчения и обязательно Трюфельный Техно Дистиллят. Запах и послевкусие — огонь! 🔥&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;День 3 — Выборг&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🚉 Приезжаем на Финляндский вокзал за полчаса до поезда, берём билеты и стоим на низком старте, чтобы успеть занять места в Ласточке и не стоять до самого &lt;a href=&quot;https://yandex.ru/maps/-/CLEFFFIL&quot;&gt;Выборга&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;🍲 Заходим в &lt;a href=&quot;https://yandex.ru/maps/-/CLEFJI8R&quot;&gt;Эспиля&lt;/a&gt; берём Выборгскую и Финскую уху. Мне повезло — к ухе поднесли рюмку. А я парень простой: наливают — пью.&lt;/p&gt;
&lt;p&gt;🚶 Теперь набравшись сил идём гулять в &lt;a href=&quot;https://yandex.ru/maps/-/CLEFFU87&quot;&gt;Старый город&lt;/a&gt;. Мне он напомнил район Галатской башни в Стамбуле — брусчатка, узкие улочки и постоянные спуски и подъёмы. Чтобы насладиться по полной — берём &lt;a href=&quot;https://yandex.ru/maps/org/fabrika_krendeley/204968038217/?ll=28.735300%2C60.712283&amp;#x26;z=16&quot;&gt;крендель&lt;/a&gt; и запиваем его глёгом.&lt;/p&gt;
&lt;p&gt;Далее идём в &lt;a href=&quot;https://yandex.ru/maps/-/CLEFbG~G&quot;&gt;Выборгский замок&lt;/a&gt; и берём билет на Башню святого Олафа с прекрасным видом на город. Остаётся совсем мало времени, едем в &lt;a href=&quot;https://yandex.ru/maps/-/CLEFbVk8&quot;&gt;парк Монрепо&lt;/a&gt; — невероятно ухоженный и живописный музей-заповедник 🌳. Здесь хорошо бы остаться на несколько часов, но у нас уже не было времени.&lt;/p&gt;
&lt;p&gt;🥪 Перед отъездом заходим перекусить в &lt;a href=&quot;https://yandex.ru/maps/org/pyshechnaya_kuptsa_markelova/228754465471?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Пышечная купца Маркелова&lt;/a&gt;. Пышки ничего, но не удивили — теща готовит намного лучше ❤️.&lt;/p&gt;
&lt;p&gt;Возвращаемся в Питер и идём во &lt;a href=&quot;https://yandex.ru/maps/-/CLEFfDOs&quot;&gt;Frank&lt;/a&gt; за пивом и рёбрами.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;День 4&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;🥐 На завтрак идем в &lt;a href=&quot;https://yandex.ru/maps/org/zoe/233783277610/?ll=30.363811%2C59.939194&amp;#x26;z=16&quot;&gt;Zoe&lt;/a&gt; берем что-то поесть, но главное — пончики и кофе.&lt;/p&gt;
&lt;p&gt;После невероятно калорийного завтрака — идем в &lt;a href=&quot;https://yandex.ru/maps/-/CLEJJKm8&quot;&gt;Таврический сад&lt;/a&gt;. Гуляем, смотрим на уток и завидуем тем, кто может гулять по таким паркам хоть каждый день. Затем, вооружившись зонтами, едем в &lt;a href=&quot;https://yandex.ru/maps/org/208387688519?si=wfhwh63q5ueaqj72bw4xbk7jd8&quot;&gt;Ботанический сад&lt;/a&gt; и гуляем там под дождем.&lt;/p&gt;
&lt;p&gt;🍛 Перед отъездом едем в &lt;a href=&quot;https://yandex.ru/maps/-/CLEFvENT&quot;&gt;Балаган&lt;/a&gt;, берем рамен, юккедян, роллы и медовуху. Снова сокрушаемся, что подобных мест в Курске нет, дохлёбываем и … отправляемся на вокзал.  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Как-то так. Куда ещё бы посоветовали сходить в Питере?
Надеюсь, когда-нибудь всё таки разберу свои Дубайские и Парижские заметки и напишу что-то подобное.&lt;/p&gt;
&lt;p&gt;😱 — если тоже считаете, что косарь за бокал пива это дорого
😎 — я айтишник, могу себе позволить&lt;/p&gt;
&lt;p&gt;@cherkashindev
#отпуск&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-354-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-354-1.jpg"/></item><item><title>Управление ожиданиями руководства и команды</title><link>https://cherkashin.dev/posts/351/</link><guid isPermaLink="true">https://cherkashin.dev/posts/351/</guid><description>Управление ожиданиями руководства и команды

В третьем модуле в Стратоплане мы обсуждали интересный момент: руководитель всегда находится в центре трёх разных ожиданий. С одной стороны — бизнес, клиенты и начальство, с другой — вся команда, и с третьей — каждый отдельный сотрудник. И с этими всеми ожиданиями необходимо...</description><pubDate>Fri, 22 Aug 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Управление ожиданиями руководства и команды&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;В третьем модуле в Стратоплане&lt;/a&gt; мы обсуждали интересный момент: руководитель всегда находится в центре трёх разных ожиданий. С одной стороны — &lt;strong&gt;бизнес, клиенты и начальство&lt;/strong&gt;, с другой — &lt;strong&gt;вся команда&lt;/strong&gt;, и с третьей — &lt;strong&gt;каждый отдельный сотрудник&lt;/strong&gt;. И с этими всеми ожиданиями необходимо уметь работать.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🎭 Модель PAEI — Ицхак Адизес&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Тут нам может помочь модель Ицхака Адизеса, которая описывает четыре главные роли менеджера.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;P (Production)&lt;/strong&gt; — это про результат &lt;strong&gt;здесь и сейчас&lt;/strong&gt;: сделали, сдали, всё работает.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A (Administration)&lt;/strong&gt; — про порядок, процессы и правила, чтобы не было хаоса.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E (Entrepreneurship)&lt;/strong&gt; — это та самая &lt;strong&gt;предпринимательская жилка&lt;/strong&gt;: видеть новые возможности, предлагать идеи и думать о будущем.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I (Integration)&lt;/strong&gt; — это &lt;strong&gt;объединение людей&lt;/strong&gt;: сплочение команды, налаживание отношений.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;На практике у каждого руководителя обычно получается ярко проявлять 1–2 функции, а остальные хромают.  В этом случае, нужно либо работать над ними, либо находить людей в команде, которые их компенсируют.&lt;/p&gt;
&lt;p&gt;Эти функции тесно связаны с жизненным &lt;a href=&quot;https://skillbox.ru/media/management/kak-nayti-geroya-kotoryy-spasyet-proekt-i-pri-chyem-tut-zhiznennye-tsikly-kompanii-po-adizesu/&quot;&gt;циклом компании&lt;/a&gt;. Например, когда я только пришёл в текущую компанию, она была где-то на стадии &lt;strong&gt;Go-Go&lt;/strong&gt; и оглядываясь назад, я понимаю, что от руководителей требовалось быть P + E:  достигать результат и понимать бизнес. Типичный пример, когда заказчику говорят, что в продукте есть нужная ему функция, и в следующие 2 недели в овральном режиме она реализуется.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🛡️ Психологическая безопасность&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ещё одна важная тема модуля — исследование Гугла под названием Аристотель.  Оно показало, что фундаментом для создания успешной команды является психологическая безопасность.&lt;/p&gt;
&lt;p&gt;Если человек не чувствует себя в безопасности — он не может быть командным игроком. Человек на уровне инстинкта будет заботиться о “выживании”, а не о работе.&lt;/p&gt;
&lt;p&gt;Психологическая безопасность — в организационном контексте - это такая рабочая среда, где люди не боятся ошибаться и откровенно высказывать своё мнение. Людей за ошибки не наказывают, а обучают.&lt;/p&gt;
&lt;p&gt;Что помогает её повышать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;демонстрация ошибок самим руководителем&lt;/li&gt;
&lt;li&gt;умение давать качественный фидбек&lt;/li&gt;
&lt;li&gt;ретроспективы без эмоций и обвинений, только факты и варианты решений&lt;/li&gt;
&lt;li&gt;чеклисты и протоколы, чтобы снизить хаос&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Кстати, можно проверить уровень безопасности в своей команде — есть опросник Эми Эдмондсон:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://psytests.org/work/tpss.html&quot;&gt;на русском&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mcleanonline.medium.com/measuring-psychological-safety-81dd1da91915&quot;&gt;на английском&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;📉 Пять пороков команды — Модель Патрика Ленсиони&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ещё одна важная тема модуля — работа с пятью пороками команд.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Взаимное недоверие — когда люди не доверяют друг другу, они скрывают ошибки и избегают взаимодействия.&lt;/li&gt;
&lt;li&gt;Избегание конфликтов — Если нет доверия, люди боятся спорить и молчат даже когда несогласны. Это главный барьер на пути к построению настоящей команде.&lt;/li&gt;
&lt;li&gt;Безответственность — «я сделал свою часть, дальше не моя проблема». Коллеги я-кают, а не мы-кают.&lt;/li&gt;
&lt;li&gt;Нетребовательность — поскольку нет ответственности, люди закрывают глаза на чужие косяки.&lt;/li&gt;
&lt;li&gt;Безразличие к результату — задачи выполняются, но общая цель никого особо не волнует.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Задача менеджера — замечать эти проблемы и вовремя исправлять, чтобы построить настоящую команду.&lt;/p&gt;
&lt;p&gt;📝 &lt;strong&gt;Итог&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сначала этот модуль откликнулся мне меньше остальных — думаю, потому что тема корпоративных культур и модель PAEI для меня сейчас не так актуальны.&lt;/p&gt;
&lt;p&gt;Но сейчас, когда я пересмотрел материал ещё раз — мне кажется другая часть, посвящённая психологической безопасности и порокам команды  — это фундаментальные моменты, без которых невозможно построение полноценной команды.&lt;/p&gt;
&lt;p&gt;||P.S. Кстати, если вы давно смотрели в сторону обучения в Стратоплане, то по промокоду 🎟️ FRIENDS можно получить скидку 15%. Нужно только указать, что нашли его у меня в канале.||&lt;/p&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-351-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-351-1.jpg"/></item><item><title>Я как-то упустил насколько быстро сейчас развивается CSS. Кажется, что через несколько лет…</title><link>https://cherkashin.dev/posts/350/</link><guid isPermaLink="true">https://cherkashin.dev/posts/350/</guid><description>Я как-то упустил насколько быстро сейчас развивается CSS. Кажется, что через несколько лет препроцессоры и другие решения будут не особо то и нужны.

CSS переменные у нас уже есть давным давноподдержка 95%Вместо БЭМА и CSS модулей сможем использовать @scopeподдержка 82%Можем сократить количество !important при переопре...</description><pubDate>Thu, 21 Aug 2025 08:32:24 GMT</pubDate><content:encoded>&lt;p&gt;Я как-то упустил насколько быстро сейчас развивается CSS. Кажется, что через несколько лет препроцессоры и другие решения будут не особо то и нужны.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS переменные у нас уже есть давным давно
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://caniuse.com/?search=custom%20properties&quot;&gt;поддержка 95%&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Вместо БЭМА и CSS модулей сможем использовать &lt;code&gt;@scope&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://caniuse.com/?search=%40scope&quot;&gt;поддержка 82%&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Можем сократить количество &lt;code&gt;!important&lt;/code&gt; при переопределении стилей, просто помещаем стили внутрь разных каскадных слоёв с помощью @layer.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://caniuse.com/?search=%40layer&quot;&gt;поддержка 93%&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Смешиваем цвета прямо в CSS
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://caniuse.com/?search=color-mix&quot;&gt;поддержка 91.5%&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;color-mix(in srgb, var(--c), white var(--pct))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Заменяем медиа выражения на if-ы
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://caniuse.com/?search=if&quot;&gt;поддержка 64%&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;color: if(style(--theme: dark): white;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; style(--theme: light): black;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; else: black);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Долой миксины, да здравствуют нативные кастомные функции
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://caniuse.com/?search=%40function&quot;&gt;поддержка 0.04%&lt;/a&gt; — свежачок 🥒&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;/* Функция для смешивания цвета с белым */&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;@function&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; --tint(--c, --pct) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  result: color-mix(in srgb, var(--c), white var(--pct));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Наверняка ещё что-то упустил, если что — подскажите 🙏.
Проверить, что все эти функции действиетльно работают (в хроме) можно 👉 &lt;a href=&quot;https://www.cherkashin.dev/demos/css-features-demo-2025/&quot;&gt;вот в этой демке&lt;/a&gt; — просто загляните &lt;a href=&quot;https://github.com/acherkashin/acherkashin.github.io/blob/main/src/pages/demos/css-features-demo-2025.html&quot;&gt;в исходники.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Подробнее здесь:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/css/layer/&quot;&gt;@layer - Управляем каскадными слоями своими руками&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/if-article?hl=ru&quot;&gt;Условные операторы CSS с новой функцией if&lt;/a&gt;()&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/740550/&quot;&gt;Знакомимся с @scope в CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.oddbird.net/2025/04/11/custom-functions/&quot;&gt;Custom CSS Functions in the Browser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#css&lt;/p&gt;</content:encoded></item><item><title>🧠 Банк памяти</title><link>https://cherkashin.dev/posts/346/</link><guid isPermaLink="true">https://cherkashin.dev/posts/346/</guid><description>🧠 Банк памяти

Я чувствую, что еле поспеваю за развитием ИИ, но потихоньку втягиваюсь и разбираюсь, как ускорить разработку. Сейчас разбираюсь с мемори бэнк и понял, что ничего нового в этом подходе нет.

Приведу простой пример.

Допустим, какая-то кнопка в новой версии приложения глючит — то работает, то нет, и тольк...</description><pubDate>Wed, 06 Aug 2025 10:41:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🧠 Банк памяти&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я чувствую, что еле поспеваю за развитием ИИ, но потихоньку втягиваюсь и разбираюсь, как ускорить разработку. Сейчас разбираюсь с &lt;a href=&quot;https://docs.cline.bot/prompting/cline-memory-bank&quot;&gt;мемори бэнк&lt;/a&gt; и понял, что ничего нового в этом подходе нет.&lt;/p&gt;
&lt;p&gt;Приведу простой пример.&lt;/p&gt;
&lt;p&gt;Допустим, какая-то кнопка в новой версии приложения глючит — то работает, то нет, и только в каких-то странных ситуациях. Что я делаю? Завожу страничку в Obsidian и начинаю расследование.&lt;/p&gt;
&lt;p&gt;Я записываю:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;когда именно кнопка отказывается работать&lt;/li&gt;
&lt;li&gt;поведение в старой версии&lt;/li&gt;
&lt;li&gt;копаюсь в запросах во вкладке Network&lt;/li&gt;
&lt;li&gt;и так далее, короче записываю, всё, что выяснил.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Потом приходит менеджер и говорит «Сань, сколько времени займет эта задача?». И тут я меняю «контекст» и разбираюсь в другой задаче.&lt;/p&gt;
&lt;p&gt;Спустя какое-то время, я возвращаюсь к проблеме с кнопкой и именно этот конспект помогает мне загрузить весь «контекст» задачи назад в мою голову.&lt;/p&gt;
&lt;p&gt;Вот так и работает мемори бэнк у ИИ-агентов. Это обычный Markdown-файл, где собрана вся нужная информация о твоём коде — например, требования к фиче. Без него ИИ может забыть какие-то детали, если начнёшь новый чат или контекст переполнится.&lt;/p&gt;
&lt;p&gt;В теории всё понятно, но вопрос как внедрить его в огромный существующий проект. Если у вас есть такой опыт, расскажите 🙏.&lt;/p&gt;
&lt;p&gt;#Ai&lt;/p&gt;</content:encoded></item><item><title>На минувших выходных в Стратоплане обсуждали специфичные фразы и «обычаи», которые употребляются…</title><link>https://cherkashin.dev/posts/345/</link><guid isPermaLink="true">https://cherkashin.dev/posts/345/</guid><description>На минувших выходных в Стратоплане обсуждали специфичные фразы и «обычаи», которые употребляются только внутри определённой команды.

Решил поделиться некоторыми из них:

Православный релиз — когда тесты не прошли, и релизишь с божьей помощью.Гипс — когда накостылил в реализации, времени переделывать нет, «загипсовал» ...</description><pubDate>Tue, 29 Jul 2025 10:02:01 GMT</pubDate><content:encoded>&lt;p&gt;На минувших выходных в Стратоплане обсуждали специфичные фразы и «обычаи», которые употребляются только внутри определённой команды.&lt;/p&gt;
&lt;p&gt;Решил поделиться некоторыми из них:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Православный релиз&lt;/strong&gt; — когда тесты не прошли, и релизишь с божьей помощью.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Гипс&lt;/strong&gt; — когда накостылил в реализации, времени переделывать нет, «загипсовал» и релизишь.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Актуально для офисных работников:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Тебе на стол кладут &lt;strong&gt;краба&lt;/strong&gt; 🦀, если ты положил прод. Краб — такой «символ» упавшего прода.&lt;/li&gt;
&lt;li&gt;Последнему человеку, который запушил костыль, ставят на стол статуэтку &lt;strong&gt;золотого костыля&lt;/strong&gt; 🏆.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;У нас, например, на одном из созвонов все молчат, пока не подключится американец и не спросит: «Is anyone talking?». Однажды он подключился на созвон, камеры у всех были выключены, он не мог понять, говорит ли кто-то, и спросил: «Is anyone talking?». Так и появился этот «обычай».&lt;/p&gt;
&lt;p&gt;А у вас в команде есть похожие фразы или обычаи?&lt;/p&gt;
&lt;p&gt;#weekphrase  #стратоплан&lt;/p&gt;</content:encoded></item><item><title>Постановка задач, фидбек и делегирование</title><link>https://cherkashin.dev/posts/344/</link><guid isPermaLink="true">https://cherkashin.dev/posts/344/</guid><description>Постановка задач, фидбек и делегирование

Второй месяц в Стратоплане был посвящен постановке задач, фидбеку и делегированию.

🏞️ Постановка задач и причем тут картинки

В постановке задач самая главная проблема заключается в том, что у исполнителя в голове одна картинка, а в голове у руководителя — совсем другая.

Пос...</description><pubDate>Wed, 23 Jul 2025 10:02:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Постановка задач, фидбек и делегирование&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;Второй месяц в Стратоплане&lt;/a&gt; был посвящен постановке задач, фидбеку и делегированию.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🏞️ Постановка задач и причем тут картинки&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В постановке задач самая главная проблема заключается в том, что у исполнителя в голове одна картинка, а в голове у руководителя — совсем другая.&lt;/p&gt;
&lt;p&gt;Постановка задач — это не создание тикетов в Джире, это работа над тем, чтобы у исполнителя в голове были правильные картинки. Если вы руководитель — вы, по сути, руководите картинками в головах других людей. Какие у людей в головах картинки — такой результат вы и получите.&lt;/p&gt;
&lt;p&gt;Например, сравните:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;«Хочу, чтобы вы активнее участвовали в планировании спринта.»&lt;/li&gt;
&lt;li&gt;«Тестировщики — приносите на планирование список задач по прошлому релизу, чтобы мы выбрали самые важные. Разработчики — делитесь своими оценками по задаче, обсуждайте, где могут быть подводные камни, и что могут затронуть изменения. Это поможет точнее оценить задачи и лучше подготовиться к тестированию.»&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Какой вариант рисует в вашей голове более чёткую картинку?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🗣️ Фидбек&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Начнём с метафоры «принцип альпинистского крюка»: если ты как альпинист хочешь забраться выше, сначала тебе нужно вбить крепко крюк, зацепиться, прицепить страховку и когда ты чувствуешь себя уверенно — можешь лезть выше.&lt;/p&gt;
&lt;p&gt;Это я к чему, есть 2 типа фидбека:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Поддерживающий&lt;/li&gt;
&lt;li&gt;Корректирующий&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Когда мы даём сотруднику &lt;strong&gt;поддерживающий фидбек&lt;/strong&gt; — забиваем тот самый крюк, чтобы он чувствовал себя уверенно. Мы рассказываем, что у него получается хорошо (на конкретных примерах), чтобы он продолжал это делать. И в итоге он будет это делать чаще и более осознанно. ||Поэтому не забывайте лайкать посты, которые вам нравятся, чтобы я понимал, что всё делаю правильно 😄||&lt;/p&gt;
&lt;p&gt;Например:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«На вчерашнем планировании ты указал на риски и предложил решение — это помогло точнее оценить задачу и избежать переработок.»&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Корректирующий&lt;/strong&gt; — мы объясняем, к чему привело определённое поведение, и что следовало бы скорректировать.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«В прошлом месяце на груминге ты не подключился к обсуждению задач по своей зоне ответственности. В итоге мы некорректно оценили задачу и допустили регрессии, потому что не учли влияние на другие модули.“»&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;💡 Поддерживающего фидбека должно быть больше чем корректирующего, чтобы человек чувствовал себя увереннее и мог морально опереться на свои сильные стороны, чтобы исправить то, что пока не получается.&lt;/p&gt;
&lt;p&gt;Жаль, что это никогда не прочитает мой инструктор по вождению, который резко жал на тормоз, вместо того, чтобы объяснить, что я делаю не так 😅.&lt;/p&gt;
&lt;p&gt;Ещё одна фраза из курса, которая особенно понравилась: «Похвала без фидбека — сахар без чая».&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🤝 Делегирование&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Тут основной момент в том, что, если вы руководитель — делегировать можно всё, кроме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;принятия ключевых решений, определения приоритетов команды и переговоров с заказчиками — иначе зачем вы вообще нужны?&lt;/li&gt;
&lt;li&gt;ключевые решения по бюджету&lt;/li&gt;
&lt;li&gt;найм, увольнения&lt;/li&gt;
&lt;li&gt;встречи 1:1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Чтобы понять, что делегировать — выпишите подробно, чем вы занимаетесь ежедневно и оставьте себе те 20% работы, которые приносят 80% пользы компании.&lt;/p&gt;
&lt;p&gt;И тут есть неочевидные моменты. Например, если вы ответственны за планирование спринта — это не значит, что вы должны делать всё сами:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;можете делегировать кому-то делать заметки&lt;/li&gt;
&lt;li&gt;оценку задач делаете совместно с другими разработчиками&lt;/li&gt;
&lt;li&gt;а приносить список косяков из прошлого спринта — делегируете тестировщикам&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Поэтому после того, как вы составили список — попробуйте раздробить задачи на более мелкие, возможно вы сможете делегировать, если не всю задачу — то какую-то её часть.&lt;/p&gt;
&lt;p&gt;И ещё пара моментов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если делегируем ответственность — нужно давать необходимые полномочия&lt;/li&gt;
&lt;li&gt;Редко бывает, что можно делегировать что-то и забыть об этом. Подбираем уровни контроля в зависимости от опыта исполнителя.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;📝 Отзыв&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Этот модуль мне понравился больше предыдущего. Тут было меньше теории и гораздо больше практики. Было много полезных аналогий и ролевых игр, где тренер наглядно показывал, как вести диалог с руководителем и давать фидбек.&lt;/p&gt;
&lt;p&gt;❤️ — оставляем подкрепляющий фидбек
🔥 — было полезно
😎 — я уже всё это знаю&lt;/p&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded></item><item><title>🔇 Митинги без шума</title><link>https://cherkashin.dev/posts/343/</link><guid isPermaLink="true">https://cherkashin.dev/posts/343/</guid><description>🔇 Митинги без шума

Пару месяцев назад я созванивался с коллегами из индийского офиса — и каждый раз это было похоже не на рабочую встречу, а на трансляцию политических дебатов. На фоне — шум, гул, кто-то спорит, кто-то смеётся.

Потом стало заметно тише. Я подумал, неужели у них в офисе стало настолько тише, но нет. ...</description><pubDate>Mon, 21 Jul 2025 10:02:01 GMT</pubDate><content:encoded>&lt;p&gt;**🔇 Митинги без шума
**
Пару месяцев назад я созванивался с коллегами из индийского офиса — и каждый раз это было похоже не на рабочую встречу, а на трансляцию политических дебатов. На фоне — шум, гул, кто-то спорит, кто-то смеётся.&lt;/p&gt;
&lt;p&gt;Потом стало заметно тише. Я подумал, неужели у них в офисе стало настолько тише, но нет. Мне рассказали, что они просто включили &lt;a href=&quot;https://support.microsoft.com/en-us/office/voice-isolation-in-microsoft-teams-calls-and-meetings-a9756ea9-4cec-44c4-aefb-6f5d17c89427&quot;&gt;&lt;em&gt;Voice Isolation&lt;/em&gt;&lt;/a&gt; в Teams.&lt;/p&gt;
&lt;p&gt;Как это работает: вы читаете небольшой текст, Teams создаёт ваш голосовой профиль, и с этого момента во время звонков AI приглушает все посторонние звуки — собеседники слышат только ваш голос.&lt;/p&gt;
&lt;p&gt;Так что, если пользуетесь Teams — обязательно настройте.&lt;/p&gt;
&lt;p&gt;А чем вы пользуетесь на работе?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Telegram&lt;/li&gt;
&lt;li&gt;Slack&lt;/li&gt;
&lt;li&gt;Teams&lt;/li&gt;
&lt;li&gt;WhatsUp&lt;/li&gt;
&lt;li&gt;Skype 😳&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-343-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-343-1.jpg"/></item><item><title>Месяц назад я баловался с Copilot&apos;ом — хотел собрать карту Курской области с местными…</title><link>https://cherkashin.dev/posts/340/</link><guid isPermaLink="true">https://cherkashin.dev/posts/340/</guid><description>Месяц назад я баловался с Copilot&apos;ом — хотел собрать карту Курской области с местными достопримечательностями. Конечно, до уровня того же Cline тулинг не дотягивает (а может, я просто не умею им пользоваться, или за последний месяц что-то именилось?), но сейчас не об этом.

В какой-то момент Copilot внезапно открыл Sim...</description><pubDate>Fri, 18 Jul 2025 10:02:01 GMT</pubDate><content:encoded>&lt;p&gt;Месяц назад я баловался с Copilot’ом — хотел собрать карту Курской области с местными достопримечательностями. Конечно, до уровня того же Cline тулинг не дотягивает (а может, я просто не умею им пользоваться, или за последний месяц что-то именилось?), но сейчас не об этом.&lt;/p&gt;
&lt;p&gt;В какой-то момент Copilot внезапно открыл &lt;strong&gt;Simple Browser&lt;/strong&gt; — прямо внутри редактора. Он позволяет выбрать элемент в верстке, и он сразу добавит скриншот и селектор этого элемента в чат (третий скрин).&lt;/p&gt;
&lt;p&gt;В одном из экспериментов я выбрал элемент карты и написал:
&lt;em&gt;“selected element should take the whole available height”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Результат на втором скрине, не знаю как — но сработало.&lt;/p&gt;
&lt;p&gt;А в Cline или других AI-агентах есть что-то такое? 🤔
Вообще расскажите, чем вы пользуетесь, какими нейронками, агентами или всё ещё кодите по старинке❓&lt;/p&gt;
&lt;p&gt;||P.S. не знаю так это или нет, но слышал, что некоторых авторов хейтят за использование тире ”–”, мол это означает, что текст написал ИИ.&lt;/p&gt;
&lt;p&gt;В общем на маке:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;держите Option и жмите минус  и получите короткое тире  — (⌥) + ”-”,&lt;/li&gt;
&lt;li&gt;если хотите тире ещё длиннее, то к Option добавьте ещё Shift — ⌥ + ⇧ + ”-”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Лёгкой пятницы вам ❤️||&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-340-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-340-1.jpg"/></item><item><title>Люди которые постоянно что-то делают вообще пробовали лежать?</title><link>https://cherkashin.dev/posts/338/</link><guid isPermaLink="true">https://cherkashin.dev/posts/338/</guid><description>Люди которые постоянно что-то делают вообще пробовали лежать?

Я вот попробовал, и это прекрасно 😅

В последние пару месяцев дел было вагон и маленькая тележка:

Наконец-то отучился на праваИдёт обучение в СтратопланеИ всё это, конечно, в дополнение к рутине и работе, после которой сил остаётся только лежать на кроват...</description><pubDate>Mon, 14 Jul 2025 10:02:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Люди которые постоянно что-то делают вообще пробовали лежать?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я вот попробовал, и это прекрасно 😅&lt;/p&gt;
&lt;p&gt;В последние пару месяцев дел было вагон и маленькая тележка:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Наконец-то отучился на права&lt;/li&gt;
&lt;li&gt;Идёт обучение в Стратоплане&lt;/li&gt;
&lt;li&gt;И всё это, конечно, в дополнение к рутине и работе, после которой сил остаётся только лежать на кровати и смотреть в потолок&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В последнее время понял: если всё время крутиться как белка в колесе, то совсем не останется сил, чтобы хоть капельку порадоваться результату. Поэтому последние две недели старался ничем кроме работы не заниматься.&lt;/p&gt;
&lt;p&gt;Я вообще человек тревожный, но на эти выходные моя тревожность немного отстала от меня. Она немного потеряла бдительность — и вот я лежу в гамаке, а до этого 3 часа проспал прямо посреди дня. Как будто даже отдохнул, силы немного восстановились.&lt;/p&gt;
&lt;p&gt;В общем, не забывайте отдыхать.&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-338-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-338-1.jpg"/></item><item><title>Модуль 1 - Работа с командой - аудит и командообразование (часть 2)</title><link>https://cherkashin.dev/posts/337/</link><guid isPermaLink="true">https://cherkashin.dev/posts/337/</guid><description>Модуль 1 - Работа с командой - аудит и командообразование (часть 2)

Итак, ненадолго вернёмся к моему обучению в Стратоплане. Я коротко упомяну то, что не вместилось в первую часть.

1️⃣ Модель Такмана

Это одна из моделей, описанных на основе анализа и статистики разных команд, которая описывает стадии, через которые ...</description><pubDate>Thu, 03 Jul 2025 11:59:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;&lt;strong&gt;Модуль 1 - Работа с командой - аудит и командообразование (часть 2)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Итак, ненадолго вернёмся к моему обучению в Стратоплане. Я коротко упомяну то, что не вместилось &lt;a href=&quot;https://t.me/cherkashindev/334&quot;&gt;в первую часть&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1️⃣ Модель Такмана&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Это одна из моделей, описанных на основе анализа и статистики разных команд, которая описывает стадии, через которые проходит коллектив, прежде чем стать настоящей командой. Это оказалось очень актуально для меня, так как наша команда сформировалась совсем недавно.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Основные стадии по Такману:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;😇 &lt;strong&gt;Формирование (Forming)&lt;/strong&gt;&lt;br&gt;
Люди только познакомились. Все вежливы, стараются понравиться, избегают острых углов. Ждут указаний от лидера, работают каждый по своей задаче.&lt;/p&gt;
&lt;p&gt;😤 &lt;strong&gt;Конфликт (Storming)&lt;/strong&gt;&lt;br&gt;
Начинают проявляться настоящие характеры. Возникают конфликты, разочарования и спады мотивации. Часто звучит: &lt;em&gt;«Я думал, будет по-другому»&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;🤝 &lt;strong&gt;Нормализация (Norming)&lt;/strong&gt;&lt;br&gt;
Появляется доверие. Люди договариваются о правилах, открыто просят помощи, привыкают друг к другу. Работать становится легче и спокойнее.&lt;/p&gt;
&lt;p&gt;🚀 &lt;strong&gt;Продуктивная работа (Performing)&lt;/strong&gt;&lt;br&gt;
Команда работает как единое целое. Участники инициативны, подстраховывают друг друга, всё идёт чётко и слаженно.&lt;/p&gt;
&lt;p&gt;🧳 &lt;strong&gt;Расставание (Adjourning)&lt;/strong&gt;&lt;br&gt;
Проект завершается. Люди делятся воспоминаниями, чуть грустят, постепенно переключаются на новые задачи.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Аналогия:&lt;/strong&gt;&lt;br&gt;
Пока писал, понял что это напоминает отношения 😅, сперва конфетно-букетный период, затем первые ссоры, а потом или расстаётесь или живёте душа в душу.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;2️⃣ Виды организационных структур&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Немного про организационные структуры — на примере нашей компании.&lt;/p&gt;
&lt;p&gt;Раньше у нас была &lt;strong&gt;функциональная модель&lt;/strong&gt;: отдельные команды разработчиков, тестировщиков, аналитиков. Каждый фокусировался на своей части.&lt;/p&gt;
&lt;p&gt;Сейчас переходим к &lt;strong&gt;кросс-функциональным командам&lt;/strong&gt;. В одной команде теперь и разработчики, и QA, и аналитики — вместе делают фичу от начала до конца. Функциональные направления при этом остаются, но больше как «сообщества практики».&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Аналогия:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Функциональная структура — это когда все контроллеры, стили, тесты лежат по отдельным папкам (&lt;code&gt;controllers/&lt;/code&gt;, &lt;code&gt;styles/&lt;/code&gt;, &lt;code&gt;tests/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Кросс-функциональная — всё, что нужно для одной фичи, в одной папке (&lt;code&gt;feature-login/&lt;/code&gt;: контроллер, стили, тесты)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Так проще координироваться и быстрее двигаться.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;3️⃣ Короткий итог&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Программа хорошо структурирована, поэтому было реально полезно&lt;/li&gt;
&lt;li&gt;Можно задать собственные вопросы в чате и получить ответы от преподавателей&lt;/li&gt;
&lt;li&gt;Есть практика в группах, но хотелось бы больше разборов собственных кейсов из жизни или более реалистичных примеров&lt;/li&gt;
&lt;li&gt;Информации реально много, но не совсем понятно, с чего начать её применять. Очень короткая выжимка со списком шагов по улучшению команды была бы невероятно полезна в нашем быстротекущем мире&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-337-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-337-1.jpg"/></item><item><title>Регулярки в мультиязычных приложениях</title><link>https://cherkashin.dev/posts/335/</link><guid isPermaLink="true">https://cherkashin.dev/posts/335/</guid><description>Регулярки в мультиязычных приложениях

Сегодня коротко и по делу: в феврале был на «Подлодке», и на докладе про i18n в React-приложениях был хороший пример про валидации форм.

Если вам нужно провалидировать имя регуляркой:

❌ /^[a-zа-я]+$/i — не используйте, иначе, как минимум многие сербы не пройдут вашу форму✅ Испол...</description><pubDate>Mon, 30 Jun 2025 10:04:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Регулярки в мультиязычных приложениях&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня коротко и по делу: в феврале был на «Подлодке», и на докладе про i18n в React-приложениях был хороший пример про валидации форм.&lt;/p&gt;
&lt;p&gt;Если вам нужно провалидировать имя регуляркой:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ &lt;code&gt;/^[a-zа-я]+$/i&lt;/code&gt; — не используйте, иначе, как минимум многие сербы не пройдут вашу форму&lt;/li&gt;
&lt;li&gt;✅ Используйте вариации следующих регулярок
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/^\w+$/u&lt;/code&gt;  — пропустит буквы &lt;strong&gt;любой&lt;/strong&gt; письменности, но вместе с ними ещё цифры и «_», так что проверяйте их отдельно, если нельзя;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/^\p{L}+$/u&lt;/code&gt; — строгий вариант: разрешает &lt;strong&gt;только&lt;/strong&gt; буквы во всех языках, поэтому имена вроде Đorđe, Nguyễn или Łukasz проходят без проблем.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#JavaScript&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-335-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-335-1.jpg"/></item><item><title>Модуль 1 - Работа с командой - аудит и командообразование (часть 1)</title><link>https://cherkashin.dev/posts/334/</link><guid isPermaLink="true">https://cherkashin.dev/posts/334/</guid><description>Модуль 1 - Работа с командой - аудит и командообразование (часть 1)

Три недели назад закончилась первая трёхдневка &quot;Модуль 1. Работа с командой - аудит и командообразование&quot; моего обучения в Стартоплане, но забегался и руки написать пост дошли лишь сейчас.

Сегодня поговорим о том, чем команда отличается от не-команды...</description><pubDate>Wed, 25 Jun 2025 10:33:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;&lt;strong&gt;Модуль 1 - Работа с командой - аудит и командообразование (часть 1)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Три недели назад закончилась первая трёхдневка “&lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;Модуль 1. Работа с командой - аудит и командообразование&lt;/a&gt;” &lt;a href=&quot;https://t.me/cherkashindev/331&quot;&gt;моего обучения в Стартоплане&lt;/a&gt;, но забегался и руки написать пост дошли лишь сейчас.&lt;/p&gt;
&lt;p&gt;Сегодня поговорим о том, чем команда отличается от не-команды.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Команда 🆚 Не-команда&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Возможно, это не очевидно, но не всегда люди, работающие вместе и решающие общую задачу, являются “настоящей” командой. Тема большая, но меня как начинающего и неопытного руководителя «зацепило» два момента:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Взаимодействие и обратная связь&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;✅ В команде — все взаимодействуют друг с другом, все дают друг другу конструктивную обратную связь. Если критикуют — то работу, а не человека и его личные качества.&lt;br&gt;
🟥 В не-команде — всё взаимодействие идёт через руководителя или неадресно.&lt;/p&gt;
&lt;p&gt;Логика примерно такая: «Ну, с ним (руководителем) я уже привык взаимодействовать, а коллегам писать влом, некомфортно, и вообще вот тот чувак меня раздражает, я тимлиду скажу, а он пусть сам со всем разберётся».&lt;/p&gt;
&lt;p&gt;Или вот ещё: как часто вы видите похожие сообщения — «Коллеги, нужно сделать вот это…». То есть коллега пишет сообщение в общий чат «в никуда» и считает, что «я написал, а там как хотите». Отклика на сообщение не ждёт — если ответа нет, ну и ладно. Знакомо такое? Мне да. 😅&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Командная цель&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;✅ В команде — каждый воспринимает командную цель как свою собственную.&lt;br&gt;
🟥 В не-команде — все сконцентрированы только на том, чтобы закрыть свои задачи.&lt;/p&gt;
&lt;p&gt;Правда, чтобы этого достичь, руководитель должен поработать с «интернализацией цели», чтобы коллеги действительно воспринимали командную цель как свою.&lt;/p&gt;
&lt;p&gt;Например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Тимлид — разработчику-интроверту: если ты сможешь затащить вот этот проект с метриками, аналитики перестанут постоянно приходить к тебе с вопросами.&lt;/li&gt;
&lt;li&gt;Тимлид — разработчику с ипотекой: если ты возьмёшь на себя вот эту дополнительную ответственность, то получишь повышение в зарплате.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Вообще, на курсе обсуждали, что для интернализации цели часто нужна &lt;strong&gt;outcome interdependence&lt;/strong&gt; — взаимозависимость членов команды.&lt;/p&gt;
&lt;p&gt;Например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если команда в целом работала хорошо — все получают премию.&lt;/li&gt;
&lt;li&gt;Если нет — то на нет и суда нет, как говорится.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;||Иначе как ты интернализируешь цель «красить кнопочки хорошо, а плохо не красить» для фронтендеров? 😄||&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Номинальная команда&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Если всё управление происходит выделенным человеком, а все остальные занимаются только своим делом, и остальное их не интересует, то команду можно назвать «номинальной».&lt;/p&gt;
&lt;p&gt;И те два пункта, которые я упомянул выше, являются очень важными, чтобы стать полноценной командой:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Без честного и открытого общения между коллегами ни о какой команде не может идти и речи.&lt;/li&gt;
&lt;li&gt;Восприятие командной цели как своей собственной и зависимость от её достижения стимулирует всех интересоваться тем, как обстоят дела у коллег, как хорошо они делают свою работу и не нужна ли им помощь.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В один пост всё не влезет, поэтому в следующий раз расскажу про:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Модель Такмана&lt;/li&gt;
&lt;li&gt;Виды организационных структур. У нас в компании как раз сейчас меняется орг структура, из-за чего я и стал Тимлидом.&lt;/li&gt;
&lt;li&gt;Небольшой отзыв в целом на модуль&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-334-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-334-1.jpg"/></item><item><title>🚧 Почему виртуальный скролл ломается на больших данных</title><link>https://cherkashin.dev/posts/333/</link><guid isPermaLink="true">https://cherkashin.dev/posts/333/</guid><description>🚧 Почему виртуальный скролл ломается на больших данных

Сегодня хочу рассказать вам вот об этой статье How to Implement Virtual Scrolling Beyond the Browser&apos;s Limit.

Когда мы говорим, что нужно оптимизировать рендеринг большого количества элементов в браузере — чаще всего речь идёт о виртуальном скроллинге.

Обычно о...</description><pubDate>Mon, 23 Jun 2025 09:51:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🚧 Почему виртуальный скролл ломается на больших данных&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня хочу рассказать вам вот об этой статье &lt;a href=&quot;https://dev.to/kohii/how-to-implement-virtual-scrolling-beyond-the-browsers-limit-16ol&quot;&gt;How to Implement Virtual Scrolling Beyond the Browser’s Limit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Когда мы говорим, что нужно оптимизировать рендеринг большого количества элементов в браузере — чаще всего речь идёт о виртуальном скроллинге.&lt;/p&gt;
&lt;p&gt;Обычно он реализуется так:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;есть элемент, назовём его &lt;code&gt;viewport&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;внутри — контейнер &lt;code&gt;content&lt;/code&gt;, в котором находится список всех элементов,&lt;/li&gt;
&lt;li&gt;этому контейнеру задаётся высота по формуле: высота одного элемента × общее количество элементов,&lt;/li&gt;
&lt;li&gt;при этом рендерятся только те элементы, которые попадают во &lt;code&gt;viewport&lt;/code&gt;, а их позиция задаётся через &lt;code&gt;transform: translateY(...)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Но знаете ли вы, что у стандартного virtual scrolling, который использует нативный скроллбар, есть ограничения?&lt;/p&gt;
&lt;p&gt;Когда мы задаём общую высоту контента, она может оказаться больше, чем максимально поддерживаемое значение в браузере. Я измерил локально и получил такие значения:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Safari: &lt;code&gt;33,554,428px&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Chrome: &lt;code&gt;16,777,200px&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Firefox: после определённого значения значение сбрасывается в 0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ограничения можете проверить сами.
👉 Здесь накидал &lt;a href=&quot;https://www.cherkashin.dev/demos/max-height-demo/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=telegram_post&amp;#x26;utm_term=max-height&quot;&gt;небольшую демку&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Из-за этого нельзя доскроллить до самого конца списка — высота просто “обрезается”.&lt;/p&gt;
&lt;p&gt;Примеры:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;&amp;#x3C;!-- Safari: высота обрежется до 33,554,428px --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; style&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;height: 9999999999999px;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;&amp;#x3C;!-- Даже без прямого указания общей высоты --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;&amp;#x3C;!-- В сумме 40,000,000px, но всё равно обрежется --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; style&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;height: 20000000px&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; style&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;height: 20000000px&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;На работе мне нужно было реализовать &lt;code&gt;JsonViewer&lt;/code&gt;, который умеет отображать огромные JSON-файлы.&lt;/p&gt;
&lt;p&gt;Я использовал &lt;a href=&quot;https://tanstack.com/virtual&quot;&gt;TanStack Virtual&lt;/a&gt; для виртуального скроллинга, но столкнулся с описанной выше проблемой — реальная высота контента была в два раза больше, чем поддерживают браузеры. Позже нашел, что в их репозитории есть &lt;a href=&quot;https://github.com/TanStack/virtual/issues/616&quot;&gt;ишью по этому поводу&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Чтобы обойти это ограничение, нужно отказаться от нативного скролла и реализовать собственную скролл-панель. В этом случае мы не задаём высоту контента, а сами рассчитываем, какие элементы должны рендериться, исходя из позиции скроллбара.&lt;/p&gt;
&lt;p&gt;Выглядит это примерно так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ITEM_HEIGHT&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 30&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// Генерируем список из 3 миллионов элементов&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Array.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;({ length: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3000000&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }, (&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; `Item ${&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// 3,000,000 × 30px = 90,000,000px (&gt; лимита браузера)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; totalHeight&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ITEM_HEIGHT&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; items.&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; viewportSize&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 300&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; App&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ScrollPane&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; contentSize&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;totalHeight&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; viewportSize&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;viewportSize&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      {&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;scrollPosition&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;        // Вычисляем, какие элементы нужно отрендерить&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; startIndex&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(scrollPosition &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ITEM_HEIGHT&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; endIndex&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;min&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          Math.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;ceil&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((scrollPosition &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; viewportSize) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ITEM_HEIGHT&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          items.&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;length&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; visibleItems&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; items.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(startIndex, endIndex);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;        // Смещение первого видимого элемента&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; startPosition&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; startIndex &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ITEM_HEIGHT&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;            style&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;              position: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;absolute&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;              top: startPosition &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; scrollPosition,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;            }&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;            {&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;visibleItems.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;              &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; style&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{ height: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;ITEM_HEIGHT&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;                {&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;              &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;            ))&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;          &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ScrollPane&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Демку, где рендерятся 3 миллиона элементов, &lt;a href=&quot;https://codesandbox.io/p/github/kohii/react-custom-scroll-example/main&quot;&gt;можно посмотреть здесь&lt;/a&gt;.
Подробнее это всё разбирается &lt;a href=&quot;https://dev.to/kohii/how-to-implement-virtual-scrolling-beyond-the-browsers-limit-16ol&quot;&gt;в статье&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#JavaScript  #Performance #Browser&lt;/p&gt;</content:encoded></item><item><title>📈 Анимации по скролу — Scroll Progress Timelines</title><link>https://cherkashin.dev/posts/332/</link><guid isPermaLink="true">https://cherkashin.dev/posts/332/</guid><description>📈 Анимации по скролу — Scroll Progress Timelines

У меня вообще не очень дела с CSS анимациями, но я наконец-то дочитал статью An Introduction To CSS Scroll-Driven Animations и решил рассказать, что такое Scroll Progress Timelines, и показать свою небольшую демку.

Обязательно откройте статью — там крутые примеры!  То...</description><pubDate>Mon, 16 Jun 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;📈 &lt;strong&gt;Анимации по скролу — Scroll Progress Timelines&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;У меня вообще не очень дела с CSS анимациями, но я наконец-то дочитал статью &lt;a href=&quot;https://www.smashingmagazine.com/2024/12/introduction-css-scroll-driven-animations/&quot;&gt;An Introduction To CSS Scroll-Driven Animations&lt;/a&gt; и решил рассказать, что такое &lt;strong&gt;Scroll Progress Timelines&lt;/strong&gt;, и &lt;a href=&quot;https://www.cherkashin.dev/demos/stories-scroll-demo/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=scroll-animation&amp;#x26;utm_term=small-demo-beginning&quot;&gt;показать свою небольшую демку.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Обязательно откройте статью — там крутые примеры!  Только посмотрите на эту &lt;a href=&quot;https://codepen.io/smashingmag/pen/jENrQGo&quot;&gt;шикарную демку с сардинами&lt;/a&gt; с &lt;del&gt;шпротами&lt;/del&gt; сардинами 🐟.&lt;/p&gt;
&lt;p&gt;Если вы писали простейшие анимации, вы знаете, что обычно нужно прописать &lt;a href=&quot;https://doka.guide/css/animation-duration/&quot;&gt;длительность цикла анимации:&lt;/a&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.element&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; animation-duration&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Scroll Progress Timelines&lt;/strong&gt; позволяют вместо времени использовать позицию скроллбара элемента. То есть, вы скроллите страницу вниз — анимация воспроизводится вперёд, скроллите вверх — прокручивается назад 🔁&lt;/p&gt;
&lt;p&gt;Самый очевидный пример — прогресс чтения статьи, который растёт, пока вы пролистываете страницу.&lt;/p&gt;
&lt;p&gt;Для этого достаточно указать:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;animation-timeline&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: scroll(&amp;#x3C;scroller&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x3C;axis&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;У функции &lt;code&gt;scroll&lt;/code&gt; есть два необязательных параметра:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;scroller&lt;/strong&gt; — указывает контейнер прокрутки: &lt;code&gt;nearest&lt;/code&gt;, &lt;code&gt;root&lt;/code&gt; или &lt;code&gt;self&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;если этих значений недостаточно, смотрите в сторону &lt;code&gt;scroll-timeline-name&lt;/code&gt; и &lt;code&gt;timeline-scope&lt;/code&gt; — они позволяют привязать анимацию к скроллбару любого элемента.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;axis&lt;/strong&gt; — направление прокрутки:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;block&lt;/code&gt; — по оси y (вертикально)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inline&lt;/code&gt; — по оси x (горизонтально)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ещё с помощью &lt;code&gt;animation-range&lt;/code&gt; можно управлять, в какой момент начинается и заканчивается анимация.&lt;/p&gt;
&lt;p&gt;Возвращаясь к примеру с прогрессбаром чтения — мы явно хотим, чтобы анимация закончилась у секции с футером высотой в 500px:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;animation-range&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: 0% calc(100% - 500px);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;**👉 **&lt;a href=&quot;https://www.cherkashin.dev/demos/stories-scroll-demo/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=scroll-animation&amp;#x26;utm_term=my-demo&quot;&gt;&lt;strong&gt;Моя демка&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Я решил накидать свою демку и попробовал реализовать анимацию прокрутки к историям в Телеграме. Если кратко:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;анимация работает только на первых 100px прокрутки
&lt;ul&gt;
&lt;li&gt;тут помог &lt;code&gt;animation-range: 0 100px&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;список сообщений смещается вниз на 100px по мере прокрутки, чтобы не мешать показу историй&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;@keyframes&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; scrollAnimation&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  margin-top&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  margin-top&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;--stories-height&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.contacts-list&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt; /* ... */&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    animation&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: scrollAnimation &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;linear&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; animation-timeline&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;scroll&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; animation-range&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;--stories-height&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; animation-fill-mode&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;both&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Чтобы анимация не застывала на промежуточном этапе, используется &lt;code&gt;scroll-snap-type: y proximity&lt;/code&gt;. Так как секция с историями &lt;code&gt;position: sticky&lt;/code&gt;, а список сообщений перемещается по анимации, то их использовать не получится. Но Claude  подсказал мне, что можно использовать псевдо-элементы со свойстов &lt;code&gt;scroll-snap-align: start&lt;/code&gt;, где они абсолютно позиционированы
&lt;ul&gt;
&lt;li&gt;первый — top: 0&lt;/li&gt;
&lt;li&gt;второй — top: 100px&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Всё написано на CSS, кроме одного: позиция скролла устанавливается через JS, чтобы истории были свернуты — как в самом Телеграме. &lt;code&gt;Если знаете как это сделать через CSS — расскажите 🙏.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🚨 &lt;a href=&quot;https://www.cherkashin.dev/demos/stories-scroll-demo/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=scroll-animation&amp;#x26;utm_term=look-here&quot;&gt;В общем переходите и поиграйтесь тут&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ещё про анимации на сайте доки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/css/scroll-snap-type/&quot;&gt;scroll-snap-type&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/css/keyframes/&quot;&gt;keyframes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/css/animation/&quot;&gt;animation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://css-tricks.com/modern-scroll-shadows-using-scroll-driven-animations/&quot;&gt;И вот ещё одна демка с тенями прокрутки&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Расскажите, вам часто приходится применять что-то подобное на реальных проектах? Я вот пока ни разу не применял, но знаю, где это могло бы мне помочь лет 6 назад 😅.&lt;/p&gt;
&lt;p&gt;#css #animations&lt;/p&gt;</content:encoded></item><item><title>🚀 Мама, я тимлид (и это не про книгу)</title><link>https://cherkashin.dev/posts/331/</link><guid isPermaLink="true">https://cherkashin.dev/posts/331/</guid><description>🚀 Мама, я тимлид (и это не про книгу)

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

У нас в компании происходят большие изменения, и п...</description><pubDate>Wed, 21 May 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🚀&lt;/strong&gt; &lt;strong&gt;Мама, я тимлид (и это не про книгу)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Последние пару лет я стараюсь подводить итоги года, а в этом году решил ещё и поставить цели на текущий год. Планы большие, и надеюсь, что хоть часть из задуманного получится реализовать. Но есть и кое-что, чего я не планировал.&lt;/p&gt;
&lt;p&gt;У нас в компании происходят большие изменения, и &lt;strong&gt;пару месяцев назад я стал тимлидом&lt;/strong&gt; .&lt;/p&gt;
&lt;p&gt;Команда такая:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;тимлид (это я 🎉)&lt;/li&gt;
&lt;li&gt;продакт 👩‍💼&lt;/li&gt;
&lt;li&gt;2 разработчика 👨‍💻👨‍💻&lt;/li&gt;
&lt;li&gt;2 manual QA 🧪🧪&lt;/li&gt;
&lt;li&gt;1 automation QA 🤖&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И если я примерно понимаю, как руководить разработчиками, то с тестировщиками всё сложнее — я только погружаюсь в их процессы и стараюсь разобраться, как планировать их нагрузку. Такие перемены меня одновременно радуют, мотивируют и пугают 😅, но я думаю — справлюсь.&lt;/p&gt;
&lt;p&gt;По счастливой случайности мне очень вовремя сделали предложение, от которого я не смог отказаться. Мне предложили бесплатно пройти курс «&lt;a href=&quot;https://stratoplan-school.com/team/&quot;&gt;Команда. Инструменты управления&lt;/a&gt;» от Стратоплана. Я же, в свою очередь, буду писать честные отзывы после каждого блока обучения — примерно раз в месяц.&lt;/p&gt;
&lt;p&gt;Так что, ксли вы задумывались о курсе для тимлидов, я смогу приоткрыть завесу и рассказать, как проходит обучение в Стратоплане и какой материал вас ждёт.&lt;/p&gt;
&lt;p&gt;🎓 &lt;strong&gt;Немного о том, как проходит поступление на курс:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сначала ты получаешь доступ в личный кабинет.&lt;/li&gt;
&lt;li&gt;Там нужно выполнить домашнее задание — оно состоит из двух частей.&lt;/li&gt;
&lt;li&gt;В первой части ты описываешь свой запрос: чего именно хочешь от обучения, какие у тебя цели. Тренер оценил мой длинный список с текущими проблемами и ожиданиями от курса 😅&lt;/li&gt;
&lt;li&gt;Вторая часть — это кейс. Представь, что ты — руководитель руководителей проектов, и на одном из проектов случился форс-мажор. Нужно принять решение, как действовать в этой ситуации.  Тут я, честно говоря, залип на пару часов — много неизвестных, куча нюансов, и в итоге приходится подключать фантазию. Но фишка в том, что правильных ответов там нет — важно, как ты рассуждаешь, как принимаешь решения.&lt;/li&gt;
&lt;li&gt;После этого назначается созвон с тренером. Можно задать все интересующие вопросы по обучению и обсудить свой кейс. Тут я понял, что с кейсом более-менее справился, но напридумывал себе коррупционных схем в организации, которые занесли меня немного не туда 🤣.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;На самом деле, интересно снова почувствовать себя немного студентом. После смены роли у меня очень много вопросов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;как планировать спринт&lt;/li&gt;
&lt;li&gt;как управлять людьми и мотивировать их&lt;/li&gt;
&lt;li&gt;как получать фидбек и правильно критиковать&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Надеюсь, курс поможет заполнить мои достаточно большие пробелы в знаниях.&lt;/p&gt;
&lt;p&gt;Обучение займёт 6 месяцев: раз в месяц, 3 дня подряд: в пятницу, субботу и воскресенье. Хорошо, что первое пятничное занятие выпадает на мой отпуск.&lt;/p&gt;
&lt;p&gt;В общем, пожелайте мне удачи 🙏 и расскажите:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Что бы вы посоветовали начинающему тимлиду?&lt;/li&gt;
&lt;li&gt;Что бы вы посоветовали самому себе, когда стали тимлидом?&lt;/li&gt;
&lt;li&gt;Каким вам хочется видеть своего тимлида?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#стратоплан&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-331-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-331-1.jpg"/></item><item><title>📝 Meeting Notes</title><link>https://cherkashin.dev/posts/330/</link><guid isPermaLink="true">https://cherkashin.dev/posts/330/</guid><description>📝 Meeting Notes

1️⃣ СитуацияВы созвонились с продактом, дизайнером, коллегой по команде — о чём-то договорились. Через какое-то время он вас спрашивает:

«А почему реализовано вот так?»Вы отвечаете:«Мы с тобой об этом договорились».А он в ответ:«Такого не было, я такого не говорил».

2️⃣ Другая ситуацияВы созвонились...</description><pubDate>Mon, 19 May 2025 08:01:01 GMT</pubDate><content:encoded>&lt;p&gt;📝 &lt;strong&gt;Meeting Notes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;strong&gt;Ситуация&lt;/strong&gt;&lt;br&gt;
Вы созвонились с продактом, дизайнером, коллегой по команде — о чём-то договорились. Через какое-то время он вас спрашивает:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«А почему реализовано вот так?»&lt;br&gt;
Вы отвечаете:&lt;br&gt;
«Мы с тобой об этом договорились».&lt;br&gt;
А он в ответ:&lt;br&gt;
«Такого не было, я такого не говорил».&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2️⃣** Другая ситуация**&lt;br&gt;
Вы созвонились, о чём-то договорились, не записали, задачу отложили на пару дней — и уже не помните, о чём договорились. Приходится снова созваниваться и вспоминать, о чём же всё-таки говорили.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Знакомо?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;✅ Решение:&lt;/strong&gt; Чтобы не было подобных ситуаций, можно вести &lt;strong&gt;протоколы встреч&lt;/strong&gt;, а затем отправляем тем, кто участвовал в обсуждении.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;❓ Зачем вести протоколы?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Чтобы не забыть. По исследованиям:&lt;br&gt;
через 20 минут мы забываем 40%,&lt;br&gt;
через час — 60%,&lt;br&gt;
через день — 70%.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Не исказить информацию с течением времени — ведь наш мозг безбожно врёт 😅&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Чтобы обратиться к заметкам в будущем и решить разногласия. Протокол встречи в какой-то степени имеет статус юридического документа.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Чтобы сохранить информацию для отсутствующих на совещании, например, если коллега был на больничном.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Передать информацию присутствующим — особенно актуально, если вы работаете в англоязычной компании, где у всех разный уровень английского.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Люди будут ответственнее относиться, например, к срокам, которые они называют ||(но это не точно 😄)||&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;✍️ Как писать протокол&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Должен быть &lt;strong&gt;кратким&lt;/strong&gt; — меньше времени на написание, меньше времени на чтение.&lt;/li&gt;
&lt;li&gt;При этом важно &lt;strong&gt;не терять контекст&lt;/strong&gt; — вы должны взглянуть на него со стороны и понять, о чём речь, через пару недель.&lt;/li&gt;
&lt;li&gt;Важно указывать, &lt;strong&gt;от кого поступила информация&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Если было принято какое-то решение, нужно описать &lt;strong&gt;контекст&lt;/strong&gt; — почему оно было принято и &lt;strong&gt;кем&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;🗂 Мой формат&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;С протоколами у меня была такая же проблема, как была раньше с ведением заметок. Я не отделял в них заметки от задач, и всё смешивалось в одну неподдерживаемую кучу. Поэтому для себя я придерживаюсь следующего очень простого формата:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agenda&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Зачем встречаемся&lt;/li&gt;
&lt;li&gt;Список вопросов, которые нужно обсудить&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Notes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Важная информация, которую следует зафиксировать&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Items&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Задачи, которые нужно сделать мне или другим членам команды&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;🛠 Инструменты&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Мы мигрировали на стек Microsoft — Teams, OneNote и т.д.&lt;br&gt;
Поэтому я просто веду заметки на одной странице в &lt;strong&gt;OneNote&lt;/strong&gt;, к которой имеет доступ команда.&lt;br&gt;
Если это встреча 1:1, я использую &lt;strong&gt;Obsidian&lt;/strong&gt;, а затем отправляю свои заметки собеседнику.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;🔗 Подробнее&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;📹 &lt;a href=&quot;https://www.youtube.com/watch?v=tpE4ABBCBuc&amp;#x26;ab_channel=ManagementChannel&quot;&gt;Видео — Meeting notes как средство коммуникации в проектной команде&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;📄 &lt;a href=&quot;https://vc.ru/u/190710-denis-opalinskii/378714-meeting-notes-agenda-prostoi-sposob-effektivno-provodit-soveshaniya&quot;&gt;Текстовая расшифровка&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А вы ведёте meeting notes? Поделитесь, как вы это делаете и какими инструментами пользуетесь&lt;/p&gt;
&lt;p&gt;#process #management&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-330-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-330-1.jpg"/></item><item><title>🎧 Потеря потерь ...</title><link>https://cherkashin.dev/posts/328/</link><guid isPermaLink="true">https://cherkashin.dev/posts/328/</guid><description>🎧 Потеря потерь ...

Моим наушникам Sennheiser стало совсем плохо. Пару лет назад я перевернулся на электросамокате — сам отделался лёгким испугом, а вот наушники получили множество трещин и переломов. С тех пор держались на честном слове, и вот теперь окончательно сдался микрофон.

Взял на замену их собрата поменьше ...</description><pubDate>Fri, 16 May 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🎧 Потеря потерь …&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Моим наушникам Sennheiser стало совсем плохо. Пару лет назад я перевернулся на электросамокате — сам отделался лёгким испугом, а вот наушники получили множество трещин и переломов. С тех пор держались на честном слове, и вот теперь окончательно сдался микрофон.&lt;/p&gt;
&lt;p&gt;Взял на замену их собрата поменьше — &lt;a href=&quot;https://www.eposaudio.com/en/gb/products/pc-8-usb-voice-over-ip-headset-1000432&quot;&gt;EPOS PC 8&lt;/a&gt;. Коллеги говорят, звук отличный, и шумодав вполне годный.&lt;/p&gt;
&lt;p&gt;Теперь думаю взять ещё одни наушники для офиса — вот не знаю, повторить покупку или попробовать что-то новое.&lt;/p&gt;
&lt;p&gt;А вы какими наушниками пользуетесь? Расскажите — может, найду для себя идеальный вариант.&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-328-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-328-1.jpg"/></item><item><title>🤖 Онбординг ИИ</title><link>https://cherkashin.dev/posts/323/</link><guid isPermaLink="true">https://cherkashin.dev/posts/323/</guid><description>🤖 Онбординг ИИ

Что происходит, когда в команде появляется новый сотрудник? Правильно — он адаптируется и старается писать код в соответствии с гайдлайнами, принятыми в команде. А помогают ему в этом документация, линтеры и ревью коллег.

По сути, ИИ — это ваш коллега, которому вы делегируете задачи, и ему тоже нужно ...</description><pubDate>Mon, 12 May 2025 08:01:01 GMT</pubDate><content:encoded>&lt;p&gt;🤖** Онбординг ИИ**&lt;/p&gt;
&lt;p&gt;Что происходит, когда в команде появляется новый сотрудник? Правильно — он адаптируется и старается писать код в соответствии с гайдлайнами, принятыми в команде. А помогают ему в этом документация, линтеры и ревью коллег.&lt;/p&gt;
&lt;p&gt;По сути, ИИ — это ваш коллега, которому вы делегируете задачи, и ему тоже нужно объяснить, как писать код. И здесь как раз пригодится документация, которую никто из ваших коллег не читает 😄, но ИИ — будет.&lt;/p&gt;
&lt;p&gt;Многие ИИ-агенты поддерживают формат “правила/инструкции”, где можно описать стандарты и архитектуру проекта. Это, по сути, обычный Markdown-файл, который будет добавляться к системному промпту при каждом запросе.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В Cline — это &lt;a href=&quot;https://docs.cline.bot/improving-your-prompting-skills/prompting#custom-instructions&quot;&gt;custom instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;В Cursor — &lt;a href=&quot;https://docs.cursor.com/context/rules&quot;&gt;rules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;В Copilot — &lt;a href=&quot;https://code.visualstudio.com/docs/copilot/copilot-customization&quot;&gt;instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;В Windsurf — &lt;a href=&quot;https://windsurf.com/editor/directory&quot;&gt;rules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Названия немного отличаются — но суть одна.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Примеры&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1️⃣ У меня Copilot упорно пытался использовать pnpm, пока я явно не указал использовать npm.&lt;/p&gt;
&lt;p&gt;2️⃣ На работе мы используем BEM и префиксы для всех имён классов, чтобы избежать коллизий. Cline, конечно, этого не понял, пока я явно не задал это в инструкциях.&lt;/p&gt;
&lt;p&gt;3️⃣ На выходных решил набросать MVP пет-проекта из бэклога. Сначала написал ТЗ с помощью ИИ, положил его в .github/instructions/&amp;#x3C;requirements-instruction.md&gt; и попросил Copilot написать проект по ТЗ. Он справился, потребовались лишь небольшие правки. Теперь при любых изменениях он уже знает требования.&lt;/p&gt;
&lt;p&gt;4️⃣ Можно попросить ИИ использовать conventional commits при генерации сообщений к коммитам.&lt;/p&gt;
&lt;p&gt;Некоторые примеры — на скринах.&lt;/p&gt;
&lt;p&gt;#ai #frontend&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-323-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-323-1.jpg"/></item><item><title>У меня есть проблема 😐</title><link>https://cherkashin.dev/posts/322/</link><guid isPermaLink="true">https://cherkashin.dev/posts/322/</guid><description>У меня есть проблема 😐

И заключается она в том, что я часто не могу насладиться отдыхом в полной мере.

Когда я ничего не делаю, я чувствую тихий голосок внутри. Он шепчет, что я теряю время, а мог бы:

📖 прочитать книгу🎓 пройти курс🛠️ начать ремонт🏋️‍♂️ сходить лишний раз в зали т.д.
Он не дает полностью расслаб...</description><pubDate>Sun, 04 May 2025 13:18:07 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;У меня есть проблема 😐&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;И заключается она в том, что &lt;strong&gt;я часто не могу насладиться отдыхом в полной мере&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Когда я ничего не делаю, я чувствую тихий голосок внутри. Он шепчет, что я теряю время, а мог бы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;📖 прочитать книгу&lt;/li&gt;
&lt;li&gt;🎓 пройти курс&lt;/li&gt;
&lt;li&gt;🛠️ начать ремонт&lt;/li&gt;
&lt;li&gt;🏋️‍♂️ сходить лишний раз в зал&lt;/li&gt;
&lt;li&gt;и т.д.
Он не дает полностью расслабиться и насладиться выходными в полную силу.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Но при этом, если я займусь чем-то, то удовольствия тоже не получу, я только сильнее устану. Получается такой замкнутый круг, в котором я постоянно должен что-то делать, чтобы ощутить мимолетное удовольствие от достижения, а затем снова окунуться в работу с головой. Ещё ситуацию усугубляет “культ успешности”, все рассказывают о своих достижениях, и кажется, что на их фоне ты какой-то лузер.&lt;/p&gt;
&lt;p&gt;Как-то я не заметил, что в какой-то момент пропало то самое ощущение беззаботности. И кажется, что произошло это когда-то давно. Но ладно, с этим я более-менее &lt;a href=&quot;https://habr.com/ru/articles/598517/&quot;&gt;научился справляться несколько лет назад&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Но аналогичная ситуация происходит, когда ты много работаешь, потом резко наступают выходные, а ты не можешь просто взять и остановиться. Тебя продолжает по инерции нести вперед, ты хочешь что-то делать дальше, несмотря на то, что сил нет. И тут требуется некоторое время чтобы наконец остановиться, перестать бежать, насладиться отдыхом и набраться сил перед новым стартом.&lt;/p&gt;
&lt;p&gt;Обычно помогает выехать куда-нибудь, где можно сменить атмосферу и много гулять, но в этот раз я остался дома — и вот, это со мной и произошло. Я пытался доделать все дела до выходных, засиживался допоздна, а когда наступили выходные появилось опустошение и нервозность. В общем, только к середине второго дня получилось усмирить себя и отпустить ситуацию, а на третий тупо лежать и смотреть сериал.&lt;/p&gt;
&lt;p&gt;Так вот, если вы чувствуете что-то такое — знайте, вы не одиноки 👋😄. И если не получилось отдохнуть в этот раз, то обязательно отдохните на следующей неделе. 😉&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-322-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-322-1.jpg"/></item><item><title>🕸️ Я в Сетке</title><link>https://cherkashin.dev/posts/321/</link><guid isPermaLink="true">https://cherkashin.dev/posts/321/</guid><description>🕸️ Я в Сетке

Я давно уже думаю, как диверсифицировать телеграмм и вести канал где-то ещё (а то вдруг с Дуровым что случится ...).

Я пробовал вести каналы:

В Дзен — трафик нулевой, ни показов, ни просмотровНа Хабре — тут получше, но нет удобного способа делать репосты из телегиНа Пикабу — и просмотры есть и бот для ...</description><pubDate>Thu, 24 Apr 2025 08:02:01 GMT</pubDate><content:encoded>&lt;p&gt;🕸️ &lt;strong&gt;Я в Сетке&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я давно уже думаю, как диверсифицировать телеграмм и вести канал где-то ещё (а то вдруг с Дуровым что случится …).&lt;/p&gt;
&lt;p&gt;Я пробовал вести каналы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В Дзен — трафик нулевой, ни показов, ни просмотров&lt;/li&gt;
&lt;li&gt;На Хабре — тут получше, но нет удобного способа делать репосты из телеги&lt;/li&gt;
&lt;li&gt;На Пикабу — и просмотры есть и бот для репостов, но на пикабу я не сижу от слова совсем&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Теперь решил попробовать Сетку, &lt;a href=&quot;https://set.ki/invite/CXLQV2G&quot;&gt;завел канал&lt;/a&gt; и пока вроде всё идет хорошо. Правда с форматирование кода — грусть грустная, надеюсь поправят. Если что Сетка — это рабочая соцсеть от &amp;#x3C;hh.ru&gt;, что-то вроде LinkedIn.&lt;/p&gt;
&lt;p&gt;В Сетке есть отдельный формат постов “Вопросы”, а ещё лента, к которой мы так привыкли. И в результате, можно получить ответы от самых разных людей.&lt;/p&gt;
&lt;p&gt;Вот некоторые из моих вопросов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://set.ki/question/6F9gbBf&quot;&gt;Как изменилась работа в финтехе с появлением ИИ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://set.ki/question/fjBmVxY&quot;&gt;Есть ли в России отечественные no-code или low-code платформы?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://set.ki/question/6WjMw3H&quot;&gt;Как получать зарплату от зарубежных компаний, если все Российские банки под санкциями?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем, если у вас есть сетка — &lt;a href=&quot;https://set.ki/channel/LWuJgdL&quot;&gt;добавляйтесь&lt;/a&gt;&lt;a href=&quot;https://set.ki/invite/CXLQV2G&quot;&gt;.&lt;/a&gt; А я пойду получу галочку)&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-321-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-321-1.jpg"/></item><item><title>🗿 Подводные камни при переходе с ES5 на ES6</title><link>https://cherkashin.dev/posts/320/</link><guid isPermaLink="true">https://cherkashin.dev/posts/320/</guid><description>🗿 Подводные камни при переходе с ES5 на ES6

Недавно мы с командой, наконец-то перешли с ES5 на ES6.

Всё прошло достаточно плавно, нам пришлось исправить всего несколько ошибок в рантайме. Почти все ошибки были в очень старых файлах, где были отключены проверки typescript с помощью @ts-nocheck.

Ошибка 1️⃣ —  Action ...</description><pubDate>Mon, 21 Apr 2025 09:02:01 GMT</pubDate><content:encoded>&lt;p&gt;🗿 &lt;strong&gt;Подводные камни при переходе с ES5 на ES6&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Недавно мы с командой, наконец-то перешли с ES5 на ES6.&lt;/p&gt;
&lt;p&gt;Всё прошло достаточно плавно, нам пришлось исправить всего несколько ошибок в рантайме. Почти все ошибки были в очень старых файлах, где были отключены проверки typescript с помощью &lt;a href=&quot;https://t.me/cherkashindev/240&quot;&gt;@ts-nocheck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ошибка&lt;/strong&gt; 1️⃣ —  Action is not a constructor&lt;/p&gt;
&lt;p&gt;Ошибка возникла в нескольких местах, где мы использовали стрелочную функцию в качестве конструктора. Раньше она не возникала, потому что стрелочная функция компилировалась в обычную &lt;code&gt;function&lt;/code&gt;.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Action&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {}; &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ES6&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; action&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Action&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// Action is not a constructor&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Action&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () {} &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ES5&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; action &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Action&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// Всё ОК&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Ошибка&lt;/strong&gt; 2️⃣ — Функции, объявленные через &lt;code&gt;let&lt;/code&gt;, больше не попадают в &lt;code&gt;window&lt;/code&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; openAction&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () {}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;window.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;openAction&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// window.openAction is not a function&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// Раньше let заменялся на var и всё работало&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; openAction&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () {}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;window.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;openAction&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// всё ок&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Дело в том, что когда переменная объявляется глобально через &lt;code&gt;var&lt;/code&gt;, она автоматически становится свойством глобального объекта &lt;code&gt;window&lt;/code&gt;. &lt;a href=&quot;https://habr.com/ru/companies/ruvds/articles/420359/&quot;&gt;Подробнее тут&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ошибка&lt;/strong&gt; 3️⃣ — Cannot access variable before initialization&lt;/p&gt;
&lt;p&gt;Одна из ошибок случалась, когда мы пытались получить доступ к переменной &lt;code&gt;promise&lt;/code&gt; до её инициализации.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Queue&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;  executing&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;  run&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;thenable&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; promise&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;reject&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;      // пытаемся получить значние promise&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      while&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.executing &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; promise) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;        // ...&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;      // ...&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// Cannot access &apos;promise&apos; before initialization&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Queue&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Раньше, &lt;code&gt;const&lt;/code&gt; превращался в &lt;code&gt;var&lt;/code&gt; и ошибки не было.  Это связано с понятием &lt;a href=&quot;https://t.me/cherkashindev/73&quot;&gt;временной мертвой зоны TDZ&lt;/a&gt;, которая не возникает у переменных, объявленных через &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Были и другие ошибки, но они по сути вариации или комбинации тех ошибок, что я привел выше.&lt;/p&gt;
&lt;p&gt;👉 Кстатии, размер бандлов уменьшился процентов на 20.&lt;/p&gt;
&lt;p&gt;#TypeScript #JavaScript&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-320-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-320-1.jpg"/></item><item><title>Особенности событий порталов в React ⚛️</title><link>https://cherkashin.dev/posts/319/</link><guid isPermaLink="true">https://cherkashin.dev/posts/319/</guid><description>Особенности событий порталов в React ⚛️

Сегодня продолжаем внимательно читать документацию React.
На прошлой неделе пофиксили небольшой баг, который возник из-за особенности всплытия событий при работе с порталами.

createPortal

Метод createPortal позволяет рендерить компонент вне текущей DOM-иерархии, но при этом он...</description><pubDate>Wed, 16 Apr 2025 07:21:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Особенности событий порталов в React&lt;/strong&gt; ⚛️&lt;/p&gt;
&lt;p&gt;Сегодня продолжаем внимательно читать документацию React.
На прошлой неделе пофиксили небольшой баг, который возник из-за особенности всплытия событий при работе с порталами.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;createPortal&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Метод &lt;code&gt;createPortal&lt;/code&gt; позволяет рендерить компонент &lt;strong&gt;вне текущей DOM-иерархии&lt;/strong&gt;, но при этом он остаётся частью &lt;strong&gt;React-дерева&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ru.react.dev/reference/react-dom/createPortal#caveats&quot;&gt;Теперь читаем документацию&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;События из порталов распространяются в соответствии с деревом React, а не деревом DOM. Например, если вы нажмёте внутри портала, и портал обёрнут в `&lt;/p&gt;&lt;div onclick=&quot;&quot;&gt;`, сработает этот обработчик `onClick`. Если это вызывает проблемы, либо остановите распространение события (stopPropogation()) внутри портала, либо переместите сам портал выше в дереве React.&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Что у нас случилось&lt;/strong&gt;❓&lt;/p&gt;
&lt;p&gt;В проекте мы недавно переписали &lt;strong&gt;тулбокс&lt;/strong&gt; — панель, из которой можно перетаскивать элементы при создании workflow.&lt;/p&gt;
&lt;p&gt;Из-за ограничений мы отказались от нативного drag-and-drop и использовали старый кастомный хук на обычных &lt;code&gt;mousedown`/`mousemove&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Что фиксили?&lt;/strong&gt; 🪲&lt;/p&gt;
&lt;p&gt;В общем, всё работал, но пользователь мог начать перестаскивать элемент &lt;strong&gt;нажав на всплывающую подсказку&lt;/strong&gt; (описание на картинке).&lt;/p&gt;
&lt;p&gt;Происходило это потому, что при нажатии на подсказку событие всплывало к родительскому компоненту элемента тулбокса, на котором вызывался обработчик &lt;code&gt;mousedown&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Причина в том, что React-ивенты всплывают по &lt;strong&gt;React-дереву&lt;/strong&gt;, а не DOM. Всё как в доке. А пофиксили это простым добавлением &lt;code&gt;stopPropogation()&lt;/code&gt; в &lt;code&gt;onMouseDown&lt;/code&gt; компонента подсказки.&lt;/p&gt;
&lt;p&gt;#react&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-319-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-319-1.jpg"/></item><item><title>Если вы этим пасмурным воскресеньем занялись поиском новой работы, загляните вот сюда — мой земляк…</title><link>https://cherkashin.dev/posts/317/</link><guid isPermaLink="true">https://cherkashin.dev/posts/317/</guid><description>Если вы этим пасмурным воскресеньем занялись поиском новой работы, загляните вот сюда — мой земляк запустил телеграм-канал с подборкой классных вакансий. Всё фильтруется нейросетями, так что в ленте только самое-самое.

Недавно, также появилась подборка МЕГАFront. Если хотите получить список самых лучших вакансий — нап...</description><pubDate>Sun, 13 Apr 2025 13:02:40 GMT</pubDate><content:encoded>&lt;p&gt;Если вы этим пасмурным воскресеньем занялись поиском новой работы, загляните &lt;a href=&quot;http://t.me/haas_vacancies&quot;&gt;вот сюда&lt;/a&gt; — мой земляк запустил телеграм-канал с подборкой классных вакансий. Всё фильтруется нейросетями, так что в ленте только самое-самое.&lt;/p&gt;
&lt;p&gt;Недавно, также появилась подборка МЕГАFront. Если хотите получить список самых лучших вакансий — &lt;a href=&quot;http://t.me/nikulin_pr&quot;&gt;напишите напрямую Саше&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Я вообще уже не помню, когда последний раз откликался на вакансии, тем более, что последние почти 8 лет, я вовсе не менял работу 😅. Обычно рекрутеры сами стучались в личку, и так я ходил по собесам. Но послдение пол года, никто не пишет, действительно ситуация на рынке изменилась?&lt;/p&gt;
&lt;p&gt;Расскажите, как сейчас лучше искать работу? &amp;#x3C;hh.ru&gt;? LinkedIn? Сетка? Телеграм-каналы с подборками?&lt;/p&gt;</content:encoded></item><item><title>⚛️ State is tied to a position in the render tree</title><link>https://cherkashin.dev/posts/316/</link><guid isPermaLink="true">https://cherkashin.dev/posts/316/</guid><description>⚛️ State is tied to a position in the render tree

Помнится в одном из своих пет проектов у меня был баг — при переходе между страницами у меня не пересоздавался zustand стор из-за чего компонент PersonalStatistic использовал стор компонента CodeReviewCharts 👇

children: [
  {
    path: &apos;/charts&apos;,
    element: (
     ...</description><pubDate>Fri, 11 Apr 2025 09:01:01 GMT</pubDate><content:encoded>&lt;p&gt;⚛️ &lt;strong&gt;State is tied to a position in the render tree&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Помнится в одном из своих пет проектов у меня был баг — при переходе между страницами у меня не пересоздавался zustand стор из-за чего компонент &lt;code&gt;PersonalStatistic&lt;/code&gt; использовал стор компонента &lt;code&gt;CodeReviewCharts&lt;/code&gt; 👇&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;children&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    path: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;/charts&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    element&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; createStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;createPersonalPageStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;CodeReviewCharts&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ),&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    path: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;/personal&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    element&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; createStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;createCommonChartsStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;PersonalStatistic&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ),&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Дело было в том, что контекст был одним и тем же компонентом &lt;code&gt;ChartsStoreProvider&lt;/code&gt;. Тогда я просто добавил &lt;code&gt;key&lt;/code&gt; для сторов и проблема ушла.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;children&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    path: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;/charts&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    element&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;charts&quot;&lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt; /*👈*/&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; createStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;createPersonalPageStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;CodeReviewCharts&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ),&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    path: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;/personal&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    element&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;personal&quot;&lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt; /*👈*/&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; createStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;createCommonChartsStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;PersonalStatistic&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ChartsStoreProvider&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ),&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Не помню было ли это в старой документации реакта, но в &lt;a href=&quot;https://react.dev/learn/preserving-and-resetting-state#state-is-tied-to-a-position-in-the-tree&quot;&gt;новой явно сказано&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;State is tied to a position in the render tree&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Состояние привязано к определённой позиции в дереве рендера.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;То, есть проблема была в том, что при переходе на страницу &lt;code&gt;/personal&lt;/code&gt;, &lt;code&gt;ChartsStoreProvider&lt;/code&gt; оставался на той же позиции в дереве и поэтому использовался “неподходящий” стейт предыдущего провайдера.&lt;/p&gt;
&lt;p&gt;Раньше я думал, что стейт живет “внутри компонента” — то, есть связан с инстансом конкретного компонента, как свойста в классе. Но документация явно говорит:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When you give a component state, you might think the state “lives” inside the component. But the state is actually held inside React. React associates each piece of state it’s holding with the correct component by where that component sits in the render tree.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Когда вы добавляете состояние (state) компоненту, может показаться, что это состояние «находится» внутри самого компонента. Однако на самом деле состояние хранится внутри React. React сопоставляет каждую единицу состояния с нужным компонентом, исходя из того, где этот компонент находится в дереве рендера.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот &lt;a href=&quot;https://react.dev/learn/preserving-and-resetting-state#same-component-at-the-same-position-preserves-state&quot;&gt;тут в демке&lt;/a&gt; это наглядно видно.&lt;/p&gt;
&lt;p&gt;А ещё &lt;code&gt;key&lt;/code&gt; &lt;a href=&quot;https://react.dev/learn/preserving-and-resetting-state#option-2-resetting-state-with-a-key&quot;&gt;можно использовать чтобы&lt;/a&gt; явно перерендерить компонент, если у него есть какой-то внутренний стейт.&lt;/p&gt;
&lt;p&gt;#react&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-316-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-316-1.jpg"/></item><item><title>ИИ для прототипирования интерфейсов</title><link>https://cherkashin.dev/posts/313/</link><guid isPermaLink="true">https://cherkashin.dev/posts/313/</guid><description>ИИ для прототипирования интерфейсов

До недавнего времени я использовал ChatGPT исключительно как помощника для генерации кода — вбросить запрос, получить сниппет, внести правки. Но все вокруг только и говорят об AI-агентах, курсоре, v0 и так я наткнулся на сервисы для онлайн генерации прототипов на основе ИИ.

Вот нес...</description><pubDate>Mon, 07 Apr 2025 09:01:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;ИИ для прототипирования интерфейсов&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;До недавнего времени я использовал ChatGPT исключительно как помощника для генерации кода — вбросить запрос, получить сниппет, внести правки. Но все вокруг только и говорят об AI-агентах, курсоре, v0 и так я наткнулся на сервисы для онлайн генерации прототипов на основе ИИ.&lt;/p&gt;
&lt;p&gt;Вот несколько подобных сервисов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bolt.new/&quot;&gt;BoltNew&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://v0.dev/&quot;&gt;v0 by Vercel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lovable.dev/&quot;&gt;lovable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Можно сказать, что это онлайн IDE, где можно сгенерировать проект по запросу, увидеть результат, задеплоить и поделиться ссылкой на прототип.&lt;/p&gt;
&lt;p&gt;Сделать полноценный проект с помощью этих сервисов, конечно, трудно, но набросать прототип и проверить гипотезу, например, возможно ли реализовать какую-то фичу с помощью какой-то библиотеки, очень удобно.&lt;/p&gt;
&lt;p&gt;А теперь немного про мой опыт 👇.&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;strong&gt;Первый опыт&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Первый раз, когда я наткнулся на v0, я попросил его сгенерировать интерфейс Айфона по скриншоту (&lt;a href=&quot;https://www.cherkashin.dev/iphone-screen-react&quot;&gt;тут демка&lt;/a&gt;). Когда я увидел результат, то в восторге побежал показывать жене. А потом понял, что шутки про замену фронтендеров на ИИ перестали быть шутками 😅.&lt;/p&gt;
&lt;p&gt;2️⃣ &lt;strong&gt;Опыт использования в работе&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В феврале мне дали большую задачу, где использовалась библиотека, в которой у меня не было ровным счётом 0 опыта, и попросили дать оценку по времени.&lt;/p&gt;
&lt;p&gt;У библиотеки, есть большой набор демок, но то, что требовалось мне —  отсутствовало. И тут я вспомнил про v0 и решил сам сгенерировать маленькие прототипы на каждую новую фичу.&lt;/p&gt;
&lt;p&gt;Нельзя сказать, что все демки были рабочие, но v0 помог мне понять возможности библиотеки, а некоторые куски кода я просто скопировал без изменений.&lt;/p&gt;
&lt;p&gt;||P.S. итоговую оценку всё же стоило умножить на 2 😅.||&lt;/p&gt;
&lt;p&gt;3️⃣ &lt;strong&gt;Ещё пример&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Также мы рассматривали вариант, сменить GoJS на &lt;a href=&quot;https://reactflow.dev/&quot;&gt;@xyflow/react&lt;/a&gt; и тут мне снова помог V0. Примеры для @xyflow/react v0 генерировал намного лучше. За пару дней я набросал небольшой прототип, который точно писал бы неделю. Я сделал скриншот дизайна в фигме, и попросил v0 сгенерировать его с использованием библиотеки.&lt;/p&gt;
&lt;p&gt;🛑 &lt;strong&gt;Минусы&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Тут конечно, важно сказать, что часто эти сервисы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;генерируют нерабочий код&lt;/li&gt;
&lt;li&gt;генерируют не совсем то, что вам нужно&lt;/li&gt;
&lt;li&gt;могут сломать весь проект после очередных изменений&lt;/li&gt;
&lt;li&gt;имеют ограниченное количество бесплатных запросов в день&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Расскажите, пользуетесь ли вы подобными сервисами и какое у вас впечатление?&lt;/p&gt;
&lt;p&gt;#Frontend #Ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-313-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-313-1.jpg"/></item><item><title>Всё достало, увольняюсь …</title><link>https://cherkashin.dev/posts/312/</link><guid isPermaLink="true">https://cherkashin.dev/posts/312/</guid><description>Всё достало, увольняюсь …</description><pubDate>Tue, 01 Apr 2025 06:05:02 GMT</pubDate><content:encoded>&lt;p&gt;Всё достало, увольняюсь …&lt;/p&gt;</content:encoded></item><item><title>🔄 Обновляем caniuse-lite</title><link>https://cherkashin.dev/posts/311/</link><guid isPermaLink="true">https://cherkashin.dev/posts/311/</guid><description>🔄 Обновляем caniuse-lite

Когда стали использовать реакт, мы взяли стандартный create-react-app, в котором использовался browserslist. Конфиг был стандартный.

  &quot;browserslist&quot;: {
    &quot;production&quot;: [
      &quot;&gt;0.2%&quot;,
      &quot;not dead&quot;,
      &quot;not op_mini all&quot;
    ],
    &quot;development&quot;: [
      &quot;last 1 chrome version&quot;,
   ...</description><pubDate>Thu, 27 Mar 2025 08:01:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🔄&lt;/strong&gt; **Обновляем caniuse-lite
**
Когда стали использовать реакт, мы взяли стандартный create-react-app, в котором использовался &lt;code&gt;browserslist&lt;/code&gt;. Конфиг был стандартный.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;  &quot;browserslist&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;    &quot;production&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;&gt;0.2%&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;not dead&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;not op_mini all&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ],&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;    &quot;development&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;last 1 chrome version&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;last 1 firefox version&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;last 1 safari version&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Потом мы, конечно, совершенно забыли как работает &lt;code&gt;browserslist&lt;/code&gt;, и успешно игнорирывали следующее сообщение при билде.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
Browserslist: caniuse-lite is outdated. Please run:

npx update-browserslist-db@latest

Why you should do it regularly: https://github.com/browserslist/update-db#readme
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Так в чём проблема? 🤔&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;caniuse-lite&lt;/code&gt; - легковесная версия, той самой базы &lt;a href=&quot;https://caniuse.com/&quot;&gt;caniuse.com&lt;/a&gt;. Время идёт, появляются новые версии браузеров, а мы используем старую базу, и все наши запросы &lt;code&gt;&quot;&gt;0.2%&quot;&lt;/code&gt; работают с браузерами пяти летней давности.&lt;/p&gt;
&lt;p&gt;То, есть запрос &lt;code&gt;&quot;&gt;0.2%&quot;&lt;/code&gt; выбирал браузеры, у которых доля рынка была больше  0.2% 5 лет назад.&lt;/p&gt;
&lt;p&gt;А это значит, что&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;async/await преобразуется в длинную партянку кода в ES5&lt;/li&gt;
&lt;li&gt;стрелочные функции &lt;code&gt;() =&gt; {}&lt;/code&gt; заменяются на &lt;code&gt;function() {}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;никаких &lt;code&gt;let/const&lt;/code&gt;, только старокрестьянский &lt;code&gt;var&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;в код попадают ненужные полифилы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем, если давно не обновляли &lt;code&gt;caniuse-lite&lt;/code&gt; открываем консоль и запускаем:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;shell&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; update-browserslist-db@latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Если у вас pnpm монорепозиторий — используйте команду:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;shell&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; up&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; caniuse-lite&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Мы обновились и наши жирные бандлы прилично похудели.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
407.31 KB (-100.86 KB) build/bundle-1.js
369.3 kB (-34.64 kB) build/bundle-2.js
220.67 KB (-18.86 kB) build/bundle-3.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#javascript   #tools&lt;/p&gt;</content:encoded></item><item><title>🏗️ Как используется паттерн простая фабрика в исходниках хромиума</title><link>https://cherkashin.dev/posts/307/</link><guid isPermaLink="true">https://cherkashin.dev/posts/307/</guid><description>🏗️ Как используется паттерн простая фабрика в исходниках хромиума

Почти год назад я говорил, что паттерн &quot;простая фабрика&quot; используется в исходниках хромиума, и вот у меня ||появилось желание|| дошли руки написать об этом.

Этот паттерн используется в реализации всем нам знакомого (кроме бэкендеров) метода document.c...</description><pubDate>Mon, 24 Mar 2025 07:29:22 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🏗️ Как используется паттерн простая фабрика в исходниках хромиума&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev/205&quot;&gt;Почти год назад я говорил&lt;/a&gt;, что паттерн “простая фабрика” используется в исходниках хромиума, и вот у меня ||появилось желание|| дошли руки написать об этом.&lt;/p&gt;
&lt;p&gt;Этот паттерн используется в реализации всем нам знакомого (кроме бэкендеров) метода &lt;code&gt;document.createElement(&apos;div&apos;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Вместо длинного списка switch/case у нас тут словарь, где по имени тега выбирается функция-конструктор и сразу вызывается.&lt;/p&gt;
&lt;p&gt;Код целиком можно посмотреть вот &lt;a href=&quot;https://source.chromium.org/chromium/chromium/src/+/main:out/mac-Debug/gen/third_party/blink/renderer/core/html_element_factory.cc;l=844&quot;&gt;здесь&lt;/a&gt; 🔗.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;cpp&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// html_element_factory.cc&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; CreateHTMLFunctionMap&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;  DCHECK&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;g_html_constructors);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  g_html_constructors &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; HTMLFunctionMap;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  // таблица соответствий тегов и функций-конструкторов&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  static&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; CreateHTMLFunctionMapData data[] &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt; // тут конструкторы всех тегов div/span/ul/li/button/h1...&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kDivTag, HTMLDivConstructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kSpanTag, HTMLSpanConstructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kMainTag, HTMLMainConstructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kUlTag, HTMLUlConstructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kLiTag, HTMLLiConstructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kButtonTag, HTMLButtonConstructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kCanvasTag, HTMLCanvasConstructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;html_names&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::kH1Tag, HTMLH1Constructor },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;    // .... и так далее&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  for&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;size_t&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(data); i&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    g_html_constructors-&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(data[i].tag.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;LocalName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(), data[i].func);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// функция — фабрика элементов&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;HTMLElement&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; HTMLElementFactory&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;Create&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; AtomicString&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; local_name&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    Document&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; document&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; CreateElementFlags&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; flags&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;g_html_constructors)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    CreateHTMLFunctionMap&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  // находим функцию-конструктор по имени тега&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  auto&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; it &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; g_html_constructors-&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(local_name);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (it &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; g_html_constructors-&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; nullptr&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  HTMLConstructorFunction function &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; it-&gt;value;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  // создаем элемент&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(document, flags);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Но это не самое интересное 🕵️‍♂️.&lt;/p&gt;
&lt;p&gt;Я достаточно долго искал этот код на гитхабе. ||И не потому что мне было плохо, когда я пытался читать C++ код.|| Я видел, что &lt;code&gt;HTMLELementFactory::Create&lt;/code&gt; &lt;a href=&quot;https://github.com/chromium/chromium/blob/9457f8bed58ffece7ac9f9b7833790024821c856/third_party/blink/renderer/core/dom/document.cc#L1119&quot;&gt;вызывается&lt;/a&gt;, но описания самой функции в коде нет.&lt;/p&gt;
&lt;p&gt;Дело в том, что файл &lt;code&gt;html_element_factory.cc&lt;/code&gt;, часть которого я привел выше — генирируется при билде. Я написал нескольким разработчикам хромиума, и пара из них скинула &lt;a href=&quot;https://source.chromium.org/chromium/chromium/src/+/main:out/mac-Debug/gen/third_party/blink/renderer/core/html_element_factory.cc&quot;&gt;мне вот эту ссылку&lt;/a&gt;, где я смог посмотреть все исходники, включая сгенирированные.&lt;/p&gt;
&lt;p&gt;А генирируется &lt;code&gt;html_element_factory.cc&lt;/code&gt; на основе:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;📜 &amp;#x3C;HTMLTagNames.in&gt; — списка тегов&lt;/li&gt;
&lt;li&gt;🏗️ ElementFactory.cpp.tmpl — шаблон файла фабрики&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#patterns #oop&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-307-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-307-1.jpg"/></item><item><title>Ну знаете ли, это уже не смешно, кто-то точно за мной следит.</title><link>https://cherkashin.dev/posts/306/</link><guid isPermaLink="true">https://cherkashin.dev/posts/306/</guid><description>Ну знаете ли, это уже не смешно, кто-то точно за мной следит.

Сначала думал, совпадение — ну ладно, один раз могло случиться. Но опять номер в отеле в двоичной системе.

В прошлый раз был 11101 = 29, в этот раз 1001 = 9. Это как-то связано с тем, что мне 29 через пару месяцев? Или кто-то передает мне пароль? Но от чег...</description><pubDate>Thu, 13 Mar 2025 16:24:37 GMT</pubDate><content:encoded>&lt;p&gt;Ну знаете ли, это уже не смешно, кто-то точно за мной следит.&lt;/p&gt;
&lt;p&gt;Сначала думал, совпадение — ну ладно, один раз могло случиться. Но опять номер в отеле в двоичной системе.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev/227&quot;&gt;В прошлый&lt;/a&gt; раз был 11101 = 29, в этот раз 1001 = 9. Это как-то связано с тем, что мне 29 через пару месяцев? Или кто-то передает мне пароль? Но от чего?&lt;/p&gt;
&lt;p&gt;Так много вопросов и мало ответов…&lt;/p&gt;
&lt;p&gt;#vacation&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-306-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-306-1.jpg"/></item><item><title>И вот несмотря на утреннюю атаку беспилотников и задержку рейса, несмотря на рамаданские пробки,…</title><link>https://cherkashin.dev/posts/302/</link><guid isPermaLink="true">https://cherkashin.dev/posts/302/</guid><description>И вот несмотря на утреннюю атаку беспилотников и задержку рейса, несмотря на рамаданские пробки, всего каких-то 23 часа путешествия и мы в Дубае 🎉.

Расскажите, куда здесь обязательно стоит сходить, а куда точно нет?

И давайте договоримся, вы мне бустите канал и спокойно работаете, а я не хвастаюсь фотками из отпуска...</description><pubDate>Tue, 11 Mar 2025 18:56:54 GMT</pubDate><content:encoded>&lt;p&gt;И вот несмотря на утреннюю атаку беспилотников и задержку рейса, несмотря на рамаданские пробки, всего каких-то 23 часа путешествия и мы в Дубае 🎉.&lt;/p&gt;
&lt;p&gt;Расскажите, куда здесь обязательно стоит сходить, а куда точно нет?&lt;/p&gt;
&lt;p&gt;И давайте договоримся, вы мне &lt;a href=&quot;https://t.me/boost/cherkashindev&quot;&gt;бустите канал&lt;/a&gt; и спокойно работаете, а я не хвастаюсь фотками из отпуска 😄.&lt;/p&gt;
&lt;p&gt;||P.S. завидую москвичам, просто взял и поехал в аэропорт и не нужно искать подходящий стыковочный поезд.||&lt;/p&gt;
&lt;p&gt;#vacation #dubai #about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-302-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-302-1.jpg"/></item><item><title>🗄️ Примеры использования IndexedDB</title><link>https://cherkashin.dev/posts/300/</link><guid isPermaLink="true">https://cherkashin.dev/posts/300/</guid><description>🗄️ Примеры использования IndexedDB

Я потихоньку начал разбираться как работает IndexedDb и нашел пару хороших примеров использования.

Я давно задумывался, как же excalidraw хранит всё, что я нарисовал, ведь картинки точно не влезут в localStorage. Ожидаемо, что для этого используется IndexedDB.

В отличии от localSt...</description><pubDate>Mon, 10 Mar 2025 14:30:25 GMT</pubDate><content:encoded>&lt;p&gt;🗄️ &lt;strong&gt;Примеры использования IndexedDB&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я потихоньку начал разбираться как работает IndexedDb и нашел пару хороших примеров использования.&lt;/p&gt;
&lt;p&gt;Я давно задумывался, как же &lt;a href=&quot;https://excalidraw.com/&quot;&gt;excalidraw&lt;/a&gt; хранит всё, что я нарисовал, ведь картинки точно не влезут в localStorage. Ожидаемо, что для этого используется IndexedDB.&lt;/p&gt;
&lt;p&gt;В отличии от localStorage, в котором доступно всего 5Mb, в indexedDb доступное пространство &lt;a href=&quot;https://rxdb.info/articles/indexeddb-max-storage-limit.html&quot;&gt;исчисляется гигабайтами.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;VK также активно использует IndexedDb, например, чтобы хранить данные об историях.&lt;/p&gt;
&lt;p&gt;Расскажите, а вы как-нибудь используете IndexedDb в своих приложениях?&lt;/p&gt;
&lt;p&gt;#frontend #indexedDb&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-301-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-301-1.jpg"/></item><item><title>В конце прошлого года ходило много слухов, что халява для программистов закончилась:</title><link>https://cherkashin.dev/posts/297/</link><guid isPermaLink="true">https://cherkashin.dev/posts/297/</guid><description>В конце прошлого года ходило много слухов, что халява для программистов закончилась:
⁃ сокращения в крупных компаниях
⁃ меньше “вкусных” вакансий

Давайте проверим, пройдите опрос ниже 👇.

P.S. этот опытный кандидат ждёт ваш оффер по адресу: г. Курск, проспект Дериглазова, лавочка №3</description><pubDate>Sat, 01 Mar 2025 10:13:33 GMT</pubDate><content:encoded>&lt;p&gt;В конце прошлого года ходило много слухов, что халява для программистов закончилась:
⁃ сокращения в крупных компаниях
⁃ меньше “вкусных” вакансий&lt;/p&gt;
&lt;p&gt;Давайте проверим, пройдите опрос ниже 👇.&lt;/p&gt;
&lt;p&gt;P.S. этот опытный кандидат ждёт ваш оффер по адресу: г. Курск, проспект Дериглазова, лавочка №3&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-297-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-297-1.jpg"/></item><item><title>Сегодня телеграм-каналу исполнилось 4 года. 🎉</title><link>https://cherkashin.dev/posts/296/</link><guid isPermaLink="true">https://cherkashin.dev/posts/296/</guid><description>Сегодня телеграм-каналу исполнилось 4 года. 🎉

Ещё с универа я хотел завести блог. На старом ноуте, даже написано несколько статей из далёкого 2017 года, которые никто никогда не увидит (и слава богу 🤣).

Помню, как написал первую статью на Хабр. Потом мы с друзьями пошли смотреть чемпионат мира 2018 в местный бар, и...</description><pubDate>Thu, 27 Feb 2025 16:36:43 GMT</pubDate><content:encoded>&lt;p&gt;Сегодня телеграм-каналу исполнилось 4 года. 🎉&lt;/p&gt;
&lt;p&gt;Ещё с универа я хотел завести блог. На старом ноуте, даже написано несколько статей из далёкого 2017 года, которые никто никогда не увидит (и слава богу 🤣).&lt;/p&gt;
&lt;p&gt;Помню, как написал первую статью на Хабр. Потом мы с друзьями пошли смотреть чемпионат мира 2018 в местный бар, и я с трясущимися руками проверял, как мне набрасывают комментарии 😄.&lt;/p&gt;
&lt;p&gt;Помню как гуглил, как создать телеграм-канал и настроить @ControllerBot, чтобы не опубликовать ничего лишнего. Помню, как стрёмно было писать посты, хотя в канале было всего 16 человек. Спустя 4 года, конечно, стало полегче. 😅&lt;/p&gt;
&lt;p&gt;Я завёл канал, когда почувствовал стагнацию, и с тех пор он подстёгивает меня изучать что-то новое и не стоять на месте 📈. Раньше было сложно придумать о чём бы написать, а теперь у меня есть бэклог с множеством идей.&lt;/p&gt;
&lt;p&gt;Часто в суете мы обо всём забываем, после каждой закрытой задачи просто берёмся за следующую. Но иногда важно остановиться, оглянуться назад и вспомнить, что было сделано и какой путь был пройден.&lt;/p&gt;
&lt;p&gt;Спасибо всем вам, что читаете — это очень мотивирует не бросать! 🎉&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-296-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-296-1.jpg"/></item><item><title>Ежегодно у нас в компании каждый сотрудник получает на почту имейл, где указано, что в течение пары…</title><link>https://cherkashin.dev/posts/294/</link><guid isPermaLink="true">https://cherkashin.dev/posts/294/</guid><description>Ежегодно у нас в компании каждый сотрудник получает на почту имейл, где указано, что в течение пары недель ему нужно пройти очередное обучение по безопасности, в котором в сотый раз расскажут что такое фишинг и тейлгейтинг. Насколько помню, это необходимо для прохождения аудита SOC (но это не точно).

Помню, лет шесть ...</description><pubDate>Mon, 24 Feb 2025 10:50:10 GMT</pubDate><content:encoded>&lt;p&gt;Ежегодно у нас в компании каждый сотрудник получает на почту имейл, где указано, что в течение пары недель ему нужно пройти очередное обучение по безопасности, в котором в сотый раз расскажут что такое фишинг и тейлгейтинг. Насколько помню, это необходимо для прохождения аудита &lt;a href=&quot;https://www.kaspersky.ru/blog/soc2-audit/23412/&quot;&gt;SOC&lt;/a&gt; (но это не точно).&lt;/p&gt;
&lt;p&gt;Помню, лет шесть назад я плохо представлял, что такое фишинг. Но в один прекрасный летний день я получил имейл от владельца компании. Уже не помню, что именно там было, но вроде как он просил мой номер телефона, чтобы со мной связаться.&lt;/p&gt;
&lt;p&gt;Я подумал: что за чушь!? Он в штатах, а я сижу в Российской деревне, прячусь от ковида. Мы никогда не разговариваем по телефону, да и на английском я говорю с трудом 😅. В общем, я проигнорил сообщение, а уже потом узнал, что это был тот самый фишинговый имейл.&lt;/p&gt;
&lt;p&gt;Думаю, насколько бы эти тренинги не казались кому-то бесполезными, они нужны, особенно для новых сотрудников.&lt;/p&gt;
&lt;p&gt;Сейчас время от времени у нас проводятся “учения”, с рассылкой фишинговых имейлов. И тех, кто кликнет на “вредоносную” ссылку, вешаю на доску позора. Шутка 😄.&lt;/p&gt;
&lt;p&gt;#job&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-294-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-294-1.jpg"/></item><item><title>Хвастаюсь.</title><link>https://cherkashin.dev/posts/292/</link><guid isPermaLink="true">https://cherkashin.dev/posts/292/</guid><description>Хвастаюсь.

Мне сегодня жена подарила такую крутую уточку, чтобы было с кем обсудить рабочие задачки.

И кабель-канал, чтобы робот-пылесос не нападал на провода.

Похоже пора заморочиться над рабочим столом, чтобы уточке не было грустно.

#about_me</description><pubDate>Sun, 23 Feb 2025 13:15:04 GMT</pubDate><content:encoded>&lt;p&gt;Хвастаюсь.&lt;/p&gt;
&lt;p&gt;Мне сегодня жена подарила такую крутую уточку, чтобы было с кем обсудить рабочие задачки.&lt;/p&gt;
&lt;p&gt;И кабель-канал, чтобы робот-пылесос не нападал на провода.&lt;/p&gt;
&lt;p&gt;Похоже пора заморочиться над рабочим столом, чтобы уточке не было грустно.&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-292-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-292-1.jpg"/></item><item><title>Ключевое слово infer</title><link>https://cherkashin.dev/posts/291/</link><guid isPermaLink="true">https://cherkashin.dev/posts/291/</guid><description>Ключевое слово infer

На тайпскрипте я пишу давно, но какие-то сложные типы практически не пишу.
Про infer я слышал, и много месяцев откладывал пятиминутное прочтение статьи, чтобы разобраться, как он работает 😄.

В итоге разобрался только во время доклада на Я 💛 Фронтенд — Антология полезностей в TypeScript .

Услов...</description><pubDate>Fri, 21 Feb 2025 10:52:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Ключевое слово infer&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На тайпскрипте я пишу давно, но какие-то сложные типы практически не пишу.
Про &lt;code&gt;infer&lt;/code&gt; я слышал, и много месяцев откладывал пятиминутное прочтение статьи, чтобы разобраться, как он работает 😄.&lt;/p&gt;
&lt;p&gt;В итоге разобрался только во время доклада на Я 💛 Фронтенд — &lt;a href=&quot;https://youtu.be/KuuY6F0ef1o?t=951&quot;&gt;Антология полезностей в TypeScript&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Условные типы&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;infer&lt;/code&gt; неотрывно связан с условными типами, поэтому начнём с них. По сути это тернарный оператор, который применяется не к переменным, а к типам.&lt;/p&gt;
&lt;p&gt;Простой пример типа &lt;code&gt;ToArray&lt;/code&gt;. Если мы передали тип-массив — условие &lt;code&gt;extends any[]&lt;/code&gt; выполняется и возвращается тот же тип &lt;code&gt;T&lt;/code&gt;, иначе создаём массив типа — &lt;code&gt;T[]&lt;/code&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ToArray&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; any&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[] &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[];&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; NumberArray&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ToArray&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// number[]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; StringArray&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ToArray&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[]&gt;; &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// string[]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;infer&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Если вы знаете английский, то поняли, что тут пойдёт речь про вывод типов. Вообще, про &lt;code&gt;infer&lt;/code&gt; удобно думать как об объявлении переменной, где тип будет выведен автоматически. То есть, TypeScript думает, можно ли что-то подставить в наше условие, чтобы оно выполнялось, если можно — выводит тип и кладёт в переменную.&lt;/p&gt;
&lt;p&gt;Теперь попробуем решить задачу обратную &lt;code&gt;ToArray&lt;/code&gt; — будем определять тип элемента в массиве.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ArrayItem&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;infer&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Item&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)[] &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Item&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; NumberItem&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ArrayItem&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[]&gt; &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// number&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; StringItem&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ArrayItem&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// string&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Тут мы просто заменяем &lt;code&gt;any&lt;/code&gt; на &lt;code&gt;infer Item&lt;/code&gt;, что означает: “выведи тип” и положи его в &lt;del&gt;переменную&lt;/del&gt; тип с именем &lt;code&gt;Item&lt;/code&gt;. И дальше просто используем Item.&lt;/p&gt;
&lt;p&gt;Также &lt;code&gt;infer&lt;/code&gt; работает с шаблонно-литеральными типами, вот так, например, можно вывести имя БЭМ-блока по элементу или модификатору&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; BemBlock&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;infer&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}__${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; ?&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    Block&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    T&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;infer&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}__${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}--${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Block1&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; BemBlock&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;login-page__form&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// login-page&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Block2&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; BemBlock&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;login-page__user--active&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// login-page&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/ruvds/articles/493716/&quot;&gt;Вывод типов в TypeScript с использованием конструкции as const и ключевого слова infer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/778190/&quot;&gt;TypeScript: infer и conditional types. Продвинутый TS на примерах&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#typescript&lt;/p&gt;</content:encoded></item><item><title>🤝 Как подружить React.lazy с дефолтным экспортом</title><link>https://cherkashin.dev/posts/288/</link><guid isPermaLink="true">https://cherkashin.dev/posts/288/</guid><description>🤝 Как подружить React.lazy с дефолтным экспортом

У нас в проекте используются только именованные экспорты. Почему — писал здесь.

Но React.lazy работает только с дефолтными экспортами, и раньше нам приходилось успокаивать eslint, приговаривая // eslint-disable-next-line import/no-default-export.

Чтобы решить проблем...</description><pubDate>Thu, 13 Feb 2025 10:01:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🤝 Как подружить React.lazy с дефолтным экспортом&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;У нас в проекте используются только именованные экспорты. Почему — &lt;a href=&quot;https://t.me/cherkashindev/109&quot;&gt;писал здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Но &lt;code&gt;React.lazy&lt;/code&gt; работает только с дефолтными экспортами, и раньше нам приходилось успокаивать eslint, приговаривая &lt;code&gt;// eslint-disable-next-line import/no-default-export&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Чтобы решить проблему &lt;a href=&quot;https://legacy.reactjs.org/docs/code-splitting.html#named-exports&quot;&gt;старая дока&lt;/a&gt; реакта предлагает создать промежуточный файл, который ре-экспортирует компонент с дефолтным экспортом.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { MyComponent &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;./ManyComponents.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Но как по мне — совсем не красиво.&lt;/p&gt;
&lt;p&gt;Но что такое дефолтный экспорт? Когда мы используем динамическую загрузку модулей с помощью &lt;code&gt;import&lt;/code&gt;, в промисе получим &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules&quot;&gt;модуль&lt;/a&gt;. А дефолтный экспорт будет храниться в поле &lt;code&gt;default&lt;/code&gt;, именованные экспорты будут храниться в соответствующих полях модуля.&lt;/p&gt;
&lt;p&gt;То есть если мы экспортируем компонент &lt;code&gt;Markdown&lt;/code&gt; с помощью именованного экспорта, то мы сможем получить к нему доступ через одноимённое свойство &lt;code&gt;Markdown&lt;/code&gt; на загруженном модуле.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; React, { lazy, Suspense } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;react&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { MySpinner } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;@private/design-system&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; MarkdownPreview&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; lazy&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; module&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;./myModule&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;    // преобразуем именованный экспорт в дефолтный&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { default: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.Markdown };&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; LazyMarkdownPreview&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Suspense&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; fallback&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;MySpinner&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;            &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;MarkdownPreview&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Suspense&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;#javascript #react&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-288-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-288-1.jpg"/></item><item><title>Запоминаем, как правильно оставлять комментарии при код-ревью</title><link>https://cherkashin.dev/posts/287/</link><guid isPermaLink="true">https://cherkashin.dev/posts/287/</guid><description>Запоминаем, как правильно оставлять комментарии при код-ревью

не 🙅‍♂️ &quot;опять ты накопипастил, ну сколько можно?!?!?!&quot;а ☝️ &quot;Consider refining the implementation to make better use of reusable code&quot;

С началом продуктивной рабочей недели 👋

#meme #codereview</description><pubDate>Mon, 10 Feb 2025 08:41:03 GMT</pubDate><content:encoded>&lt;p&gt;Запоминаем, как правильно оставлять комментарии при код-ревью&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;не 🙅‍♂️ “опять ты накопипастил, ну сколько можно?!?!?!”&lt;/li&gt;
&lt;li&gt;а ☝️ “Consider refining the implementation to make better use of reusable code”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;С началом продуктивной рабочей недели 👋&lt;/p&gt;
&lt;p&gt;#meme #codereview&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-287-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-287-1.jpg"/></item><item><title>Иногда бывает, засидишься за работой, пытаясь доделать интересную (или не очень) задачу. Крутишь её…</title><link>https://cherkashin.dev/posts/286/</link><guid isPermaLink="true">https://cherkashin.dev/posts/286/</guid><description>Иногда бывает, засидишься за работой, пытаясь доделать интересную (или не очень) задачу. Крутишь её так и эдак 🤔, но ничего не выходит.

Потом смотришь на часы— пора заканчивать, а задача так и не сделана. Опускаешь крышку ноута, но в голове она продолжает крутиться.

А как же это решить? 🤯 Мысленно перебираешь все в...</description><pubDate>Wed, 05 Feb 2025 11:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Иногда бывает, засидишься за работой, пытаясь доделать интересную (или не очень) задачу. Крутишь её так и эдак 🤔, но ничего не выходит.&lt;/p&gt;
&lt;p&gt;Потом смотришь на часы— пора заканчивать, а задача так и не сделана. Опускаешь крышку ноута, но в голове она продолжает крутиться.&lt;/p&gt;
&lt;p&gt;А как же это решить? 🤯 Мысленно перебираешь все возможные варианты решения. А почему же это не сработало? А может быть, вот так сделать? А если тут поле добавить? А есть ли у нас вообще эти данные? А что, если сделать дополнительный запрос на сервер? А потом… а потом…&lt;/p&gt;
&lt;p&gt;А потом наступает тревожность, и нормально уснуть уже не получается.&lt;/p&gt;
&lt;p&gt;У вас бывает такое? 🤷‍♂️&lt;/p&gt;
&lt;p&gt;Но всё же чувство, когда ты всё-таки разобрался и всё получилось - бесценно.&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-286-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-286-1.jpg"/></item><item><title>✨ViewTransitionAPI view-transition-name</title><link>https://cherkashin.dev/posts/284/</link><guid isPermaLink="true">https://cherkashin.dev/posts/284/</guid><description>✨ViewTransitionAPI view-transition-name

Прочитал статью &quot;Same-document view transitions for single-page applications&quot; и решил запилить свою демку с открытием приложения как на айфоне, используя viewTransitionAPI.

Анимация реализуется с помощью CSS свойства view-transition-name. Так мы указываем, что анимация для этог...</description><pubDate>Tue, 28 Jan 2025 07:28:08 GMT</pubDate><content:encoded>&lt;p&gt;✨&lt;strong&gt;ViewTransitionAPI view-transition-name&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Прочитал статью “&lt;a href=&quot;https://developer.chrome.com/docs/web-platform/view-transitions/same-document&quot;&gt;Same-document view transitions for single-page applications&lt;/a&gt;” и решил запилить свою демку с открытием приложения как на айфоне, используя viewTransitionAPI.&lt;/p&gt;
&lt;p&gt;Анимация реализуется с помощью CSS свойства &lt;code&gt;view-transition-name&lt;/code&gt;. Так мы указываем, что анимация для этого элемента должна происходить отдельно.&lt;/p&gt;
&lt;p&gt;⚠️ Значение &lt;code&gt;view-transition-name&lt;/code&gt; должно быть уникальным, если у разных элементов одно и то же значение &lt;code&gt;view-transition-name&lt;/code&gt;, анимация скипнется и появится ошибка в консоли.&lt;/p&gt;
&lt;p&gt;Но есть нюанс, на время перехода можно указать &lt;code&gt;view-transition-name&lt;/code&gt; разным элементам. Так мы скажем браузеру, что один элемент должен анимироваться в другой.&lt;/p&gt;
&lt;p&gt;В реакте, пока только появляется экспериментальная поддержка &lt;a href=&quot;https://motion.dev/blog/reacts-experimental-view-transition-api&quot;&gt;ViewTransition&lt;/a&gt;, поэтому придётся использовать &lt;code&gt;flushSync&lt;/code&gt;, чтобы запустить рендер синхронно, что не есть гуд для производительности.&lt;/p&gt;
&lt;p&gt;Код перехода выглядит так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; handleAppOpened&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; React&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;MouseEvent&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;HTMLButtonElement&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    openedApp.current &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (e.target &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; HTMLButtonElement&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;    // выставляем иконке такой же viewTransitionName как и для экрана приложения&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    openedApp.current.style.viewTransitionName &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;app-content&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt; // запускаем переход&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    document.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;startViewTransition&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (openedApp.current?.style) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;     // сбрасываем viewTransitionName для иконки&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        openedApp.current.style.viewTransitionName &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;   // синхронный рендер&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;      flushSync&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; setApp&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(appName));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Во время анимации появляется дерево псевдо-элементов.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;view-transition&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  ::view-transition-group(root)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  ::view-transition-group(&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;app-content&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ::view-transition-old(&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;app-content&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ::view-transition-new(&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;app-content&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Так мы можем выставить кастомную анимацию:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::view-transition-new(&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;app-content&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  animation&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;300&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;ms&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ease&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;::view-transition-old(&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;app-content&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  animation&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;300&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;ms&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ease&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; reverse&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Отлаживать анимацию, можно с помощью панели Animations:
⚙️ &gt; More tools &gt; Animations&lt;/p&gt;
&lt;p&gt;📂 &lt;a href=&quot;https://github.com/acherkashin/iphone-screen-react&quot;&gt;Исходники здесь&lt;/a&gt;
🌐 &lt;a href=&quot;https://www.cherkashin.dev/iphone-screen-react/&quot;&gt;Демка здесь&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://motion.dev/blog/reacts-experimental-view-transition-api&quot;&gt;Revealed: React’s experimental animations API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://native-transitions.netlify.app/&quot;&gt;Демка с расстановкой футболистов на футбольном поле&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/reference/react-dom/flushSync&quot;&gt;React flushSync&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend@cherkashindev&lt;/p&gt;</content:encoded></item><item><title>Как-то редко я стал что-то рекомендовать посмотреть/почитать, но сегодня пришел не с пустыми…</title><link>https://cherkashin.dev/posts/283/</link><guid isPermaLink="true">https://cherkashin.dev/posts/283/</guid><description>Как-то редко я стал что-то рекомендовать посмотреть/почитать, но сегодня пришел не с пустыми руками, а с докладом &quot;Как умение продавать помогает разработчику / Андрей Кузнецов (РБС)&quot;.

Советую посмотреть доклад целиком, но мне больше всего понравилось про Эффект маятника ⚖️.

Так сложилось, что порадовать человека гора...</description><pubDate>Fri, 24 Jan 2025 11:29:01 GMT</pubDate><content:encoded>&lt;p&gt;Как-то редко я стал что-то рекомендовать посмотреть/почитать, но сегодня пришел не с пустыми руками, а с докладом “&lt;a href=&quot;https://www.youtube.com/watch?v=iJ0h-6KsD34&amp;#x26;t=1852s&amp;#x26;ab_channel=FrontendChannel&quot;&gt;Как умение продавать помогает разработчику / Андрей Кузнецов (РБС)&lt;/a&gt;“.&lt;/p&gt;
&lt;p&gt;Советую посмотреть доклад целиком, но мне больше всего понравилось про &lt;strong&gt;Эффект маятника&lt;/strong&gt; ⚖️.&lt;/p&gt;
&lt;p&gt;Так сложилось, что порадовать человека гораздо сложнее, чем напугать его. Но если сперва напугать, то порадовать будет гораздо проще.&lt;/p&gt;
&lt;p&gt;Это называют эффектом маятника, потому что эмоции сначала сильно качаются в одну сторону (страх), а потом так же сильно летят обратно в другую (радость), делая её ещё ярче.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пример, который все поймут&lt;/strong&gt;: засовываешь руку в карман, а телефона нет 🤷‍♂️, и в панике начинаешь везде его искать. Находишь телефон во внутреннем кармане, и радости нет конца, ничего не изменилось — но вы счастливы.&lt;/p&gt;
&lt;p&gt;💬 &lt;strong&gt;Как это пригодится в переговорах?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На этих “качелях” 🎢 можно сделать “продажу” — “Мол, смотри как всё плохо, но у нас есть волшебная таблетка 💊“. И человек с радостью купит эту таблетку.&lt;/p&gt;
&lt;p&gt;Приходите на переговоры и запугиваете начальство:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Вот у нас есть давно написанный код, и из-за него постоянно появляются баги в продукте. Из-за одного такого бага, от нас ушел клиент.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;После того, как все напуганы и в панике грызут ногти - предложите им лекарство:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Но если бы мы делили время, покрыли бы этот код тестами и провели рефакторинг — всех этих проблем можно было бы избежать.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;📌 И ещё несколько моментов из доклада:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ключевая часть продаж — переговоры.&lt;/li&gt;
&lt;li&gt;Все мы что-то продаём.&lt;/li&gt;
&lt;li&gt;Старайтесь не называть срок по задачам первым.&lt;/li&gt;
&lt;li&gt;Если кто-то пытается уговорить вас сделать задачу быстрее — не делайте скидку сразу.&lt;/li&gt;
&lt;li&gt;Если делаете скидку — обосновывайте. Мы сделаем задачу за 8, а не за 14 дней, но возможно будут проблемы с производительностью. Или мы не успеем сделать вот эту часть функционала.&lt;/li&gt;
&lt;li&gt;Не используйте круглые цифры. В “не круглые цифры” люди верят охотнее, ведь им кажется, что это результат какого-то глубокого анализа. Например, говорите, что задача займет не 5 дней, а будет сделана к 12 часам в четверг.&lt;/li&gt;
&lt;li&gt;Никогда никого не перебивайте.&lt;/li&gt;
&lt;li&gt;Вежливо отказывайте собеседнику. Понимать - не значит соглашаться.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#softskills #fridayreading&lt;/p&gt;</content:encoded></item><item><title>Жизнь без Канбан досок в Obisidian 💎</title><link>https://cherkashin.dev/posts/282/</link><guid isPermaLink="true">https://cherkashin.dev/posts/282/</guid><description>Жизнь без Канбан досок в Obisidian 💎

После перехода с Notion на Obsidian я начал упрощать всё, что только можно. Например, в Obsidian нет нативной поддержки канбан-досок. Я попробовал плагин Projects для управления постами, которые перенёс из Notion.

Но у него есть проблема: статусы у новых записей почему-то слетают...</description><pubDate>Mon, 20 Jan 2025 11:01:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Жизнь без Канбан досок в Obisidian 💎&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;После перехода с Notion на Obsidian я начал упрощать всё, что только можно. Например, в Obsidian нет нативной поддержки канбан-досок. Я попробовал плагин &lt;a href=&quot;https://t.me/cherkashindev/225&quot;&gt;Projects&lt;/a&gt; для управления постами, которые перенёс из Notion.&lt;/p&gt;
&lt;p&gt;Но у него есть проблема: статусы у новых записей почему-то слетают. Возможно я что-то настроил не так, но мне приходится выставлять их по несколько раз, что, мягко говоря, раздражает.&lt;/p&gt;
&lt;p&gt;И тут я задумался: а ведь канбан — это просто набор папок.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
Посты  
├── 0.Backlog  
├── 1.Next  
├── 2.InProgress  
└── 3.Done  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Для простых случаев этого более чем достаточно. Иногда самое простое решение оказывается самым удобным.&lt;/p&gt;
&lt;p&gt;А ещё мне нравится, что в Obsidian всё — это просто файлы и папки. Это даёт огромную свободу для оптимизаций с помощью скриптов. Например, я попросил ChatGPT написать скрипт, который автоматически переносит готовые посты в папку “3.Done”.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;bash&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;Moving files with the &apos;done&apos; tag to the Done folder...&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;# Paths to the Posts and Done folders&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;POSTS_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$HOME&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;/Documents/Obsidian Vault/Посты&quot;&lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;  # Adjust the base path to your Obsidian vault&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;DONE_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$HOME&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;/Documents/Obsidian Vault/Посты/3.Done&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;# Ensure the Done folder exists&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [ &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$DONE_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; ]; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;  mkdir&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; -p&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$DONE_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;Failed to create Done folder: &lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$DONE_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    exit&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;# Check if the Posts folder exists&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [ &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$POSTS_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; ]; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;Posts folder does not exist: &lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$POSTS_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  exit&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;# Process files&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;Scanning for markdown files with #done tag in &lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$POSTS_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;...&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;moved_count&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; file &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$POSTS_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;/*.md&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  # Skip if no markdown files are found&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [ &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; -e&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$file&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; ]; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;No markdown files found in &lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$POSTS_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    break&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  fi&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  # Check if the file contains the #done tag&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; -q&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;✅ Done&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$file&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    mv&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$file&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$DONE_FOLDER&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;/&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x26;&amp;#x26; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;      echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;Moved: $(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;basename&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$file&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      ((moved_count&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;      echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;Failed to move: $(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;basename&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$file&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  fi&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;done&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;Finished. Total files moved: &lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;$moved_count&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;#obsidian&lt;/p&gt;</content:encoded></item><item><title>🗂️Папка с Курскими ИТ-каналами</title><link>https://cherkashin.dev/posts/281/</link><guid isPermaLink="true">https://cherkashin.dev/posts/281/</guid><description>🗂️Папка с Курскими ИТ-каналами

В прошлом году решил, что было бы неплохо собрать все Курские ИТ каналы в одну папку, и вот что получилось

👉 https://t.me/addlist/CcKwwK1G9AxMjEy

Даже если вы не из Курска — обязательно добавляйте папку, точно найдёте для себя что-то интересное.

Пара слов о каждом:

@cherkashindev —...</description><pubDate>Mon, 13 Jan 2025 10:09:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🗂️Папка с Курскими ИТ-каналами&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В прошлом году решил, что было бы неплохо собрать все Курские ИТ каналы в одну папку, и вот что получилось&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://t.me/addlist/CcKwwK_1G9AxMjEy&quot;&gt;https://t.me/addlist/CcKwwK_1G9AxMjEy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Даже если вы не из Курска — обязательно добавляйте папку, точно найдёте для себя что-то интересное.&lt;/p&gt;
&lt;p&gt;Пара слов о каждом:&lt;/p&gt;
&lt;p&gt;@cherkashindev — это собственно я, пишу в основном о вебе, GTD и иногда о C#&lt;/p&gt;
&lt;p&gt;@polovnyov_journal — Вася - техдир в Бюро Горбунова, пишет о разработке, тестировании и рабочих процессах&lt;/p&gt;
&lt;p&gt;@rich_developer — Саша - CEO в HaaS Platform, пишет про найм, поиск работы и публикует вкусные вакансии&lt;/p&gt;
&lt;p&gt;@andvink — Андрей пишет про ИИ и автоматизацию разработки. Сменил стек с веба на ML&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/likelivinghere/358&quot;&gt;@likelivinghere&lt;/a&gt; — Виталик - QA Lead, пишет о стендапе, релокации и возвращении в Россию&lt;/p&gt;
&lt;p&gt;@tony_malyshev — Антон пишет об аналитике, маркетинге и нейросетях&lt;/p&gt;
&lt;p&gt;@gameFromTheInside — Кирилл пишет о разработке игр, в прошлом году опубликовал “&lt;a href=&quot;https://yandex.ru/games/app/385953#app-id=385953&amp;#x26;catalog-session-uid=catalog-10adc24b-703c-501b-af40-0d4bf795b1b2-1736687468051-ab91&amp;#x26;rtx-reqid=253779369526639038&amp;#x26;pos=%7B%22listType%22%3A%22suggested%22%2C%22tabCategory%22%3A%22search%22%7D&amp;#x26;redir-data=%7B%22block%22%3A%22search%22%2C%22block_index%22%3A0%2C%22card%22%3A%22adaptive_recommended_new%22%2C%22col%22%3A0%2C%22first_screen%22%3A1%2C%22page%22%3A%22search%22%2C%22rn%22%3A287082134%2C%22row%22%3A0%2C%22rtx_reqid%22%3A%228841485696809060051%22%2C%22same_block_index%22%3A0%2C%22wrapper%22%3A%22grid-list%22%2C%22request_id%22%3A%221736687501244655-12042893112810719084-gq3pz34xiyls3ovx-BAL%22%2C%22http_ref%22%3A%22https%253A%252F%252Fyandex.ru%252Fgames%252Fsearch%253Flang%253Dru%2526query%253D%2525D0%2525A2%2525D0%2525B0%2525D0%2525BD%2525D0%2525BA%2525D0%2525B8%2525203D%22%7D&amp;#x26;search_query=%D0%A2%D0%B0%D0%BD%D0%BA%D0%B8%203D&quot;&gt;Танки 3D: Дикая арена&lt;/a&gt;” в Яндекс Играх&lt;/p&gt;
&lt;p&gt;@kavyrshing — Саша пишет про около-айти, аджайл и коучинг&lt;/p&gt;
&lt;p&gt;@dyuminblog — Вадим - дизайнер с 20-летним опытом работы&lt;/p&gt;
&lt;p&gt;Если кого-то упустил, то обязательно пишите — добавлю&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://t.me/addlist/CcKwwK_1G9AxMjEy&quot;&gt;Папка - ИТ Курск&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>React приложение без сборщиков</title><link>https://cherkashin.dev/posts/280/</link><guid isPermaLink="true">https://cherkashin.dev/posts/280/</guid><description>React приложение без сборщиков

Иногда нужно набросать небольшой пример или демку на реакте, но не хочется создавать новый проект, где установится +100500 пакетов. Создавать проект в песочнице типа codesandbox тоже лень. Есть вариант попроще:

1️⃣ Подключаем react и react-dom через CDN

&lt;script src=&quot;https://unpkg.com/r...</description><pubDate>Fri, 10 Jan 2025 07:12:32 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;React приложение без сборщиков&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Иногда нужно набросать небольшой пример или демку на реакте, но не хочется создавать новый проект, где установится +100500 пакетов. Создавать проект в песочнице типа codesandbox тоже лень. Есть вариант попроще:&lt;/p&gt;
&lt;p&gt;1️⃣ Подключаем react и react-dom через CDN&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;https://unpkg.com/react@18/umd/react.development.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;https://unpkg.com/react-dom@18/umd/react-dom.development.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;2️⃣ Подключаем babel через CDN&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;3️⃣ Добавляем root&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;4️⃣ Добавляем script с типом “text/babel”, внутри которого мы можем использовать JSX&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;text/babel&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;sciprt&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Получаем следующий код&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;!&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; html&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; lang&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;width=device-width, initial-scale=1.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;React Without Bundler&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;https://unpkg.com/react@18/umd/react.development.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;https://unpkg.com/react-dom@18/umd/react-dom.development.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;text/babel&quot;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; defer&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; App&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;            const&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;count&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;setCount&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; React.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;useState&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; style&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{ textAlign: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;center&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, marginTop: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;50px&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Счётчик: &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;count&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; setCount&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(count &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;-&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; setCount&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; style&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{ margin: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;0 10px&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                        Сброс&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                    &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; setCount&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(count &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;+&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;                &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;            );&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        };&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        ReactDOM.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;createRoot&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(document.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;render&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;App&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;5️⃣ Для максимальной простоты — создаём сниппет в VS Code&lt;/p&gt;
&lt;p&gt;👉 CMD + SHIFT + P &gt; Configure Snippets &gt; New Global Snippets file и вставляете туда&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;    &quot;React Without Bundler HTML&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;        &quot;prefix&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;react-html&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;  &quot;scope&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;html&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;        &quot;body&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&amp;#x3C;!DOCTYPE html&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&amp;#x3C;html lang=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;en&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&amp;#x3C;head&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;meta charset=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;UTF-8&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;meta name=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;viewport&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; content=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;width=device-width, initial-scale=1.0&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;title&gt;React Without Bundler&amp;#x3C;/title&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;script src=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;https://unpkg.com/react@18/umd/react.development.js&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&gt;&amp;#x3C;/script&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;script src=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;https://unpkg.com/react-dom@18/umd/react-dom.development.js&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&gt;&amp;#x3C;/script&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;script src=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;https://unpkg.com/@babel/standalone/babel.min.js&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&gt;&amp;#x3C;/script&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&amp;#x3C;/head&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&amp;#x3C;body&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;div id=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;root&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&gt;&amp;#x3C;/div&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;script type=&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;text/babel&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; defer&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;        const { useState } = React;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;        function App() {&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;            const [count, setCount] = useState(0);&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;            return (&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                &amp;#x3C;div style={{ textAlign: &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;center&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;, marginTop: &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;50px&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; }}&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                    &amp;#x3C;h1&gt;Счётчик: {count}&amp;#x3C;/h1&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                    &amp;#x3C;button onClick={() =&gt; setCount(count - 1)}&gt;-&amp;#x3C;/button&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                    &amp;#x3C;button onClick={() =&gt; setCount(0)} style={{ margin: &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;0 10px&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; }}&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                        Сброс&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                    &amp;#x3C;/button&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                    &amp;#x3C;button onClick={() =&gt; setCount(count + 1)}&gt;+&amp;#x3C;/button&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;                &amp;#x3C;/div&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;            );&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;        };&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;        ReactDOM.createRoot(document.getElementById(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;root&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;)).render(&amp;#x3C;App /&gt;);&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;    &amp;#x3C;/script&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&amp;#x3C;/body&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;            &quot;&amp;#x3C;/html&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        ],&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;#react #vscode&lt;/p&gt;</content:encoded></item><item><title>Выходные пролетели, как обычно! Успели отдохнуть?</title><link>https://cherkashin.dev/posts/270/</link><guid isPermaLink="true">https://cherkashin.dev/posts/270/</guid><description>Выходные пролетели, как обычно! Успели отдохнуть?

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

Во время поездки погода была отличная — на несколько дней ударил мороз, и удалось насладиться зимой, которая в Курск заглядывает всё реже (сегодня +6).

Суздаль —...</description><pubDate>Wed, 08 Jan 2025 16:22:20 GMT</pubDate><content:encoded>&lt;p&gt;Выходные пролетели, как обычно! Успели отдохнуть?&lt;/p&gt;
&lt;p&gt;Я первую половину выходных батонился на кровати и смотрел сериалы, а вторую гулял по Владимиру и Суздали.&lt;/p&gt;
&lt;p&gt;Во время поездки погода была отличная — на несколько дней ударил мороз, и удалось насладиться зимой, которая в Курск заглядывает всё реже (сегодня +6).&lt;/p&gt;
&lt;p&gt;Суздаль — это что-то особенное, словно русская сказка оживает наяву:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Около 50 церквей на небольшой городок — удивительное ощущение духовности.&lt;/li&gt;
&lt;li&gt;Старинные дома в центре с резными наличниками и деревянными воротами — будто из прошлого века.&lt;/li&gt;
&lt;li&gt;Лошади с санями, неспешно везущие туристов, — атмосфера уюта и зимнего волшебства.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Теперь как-то нужно вырваться туда летом …&lt;/p&gt;
&lt;p&gt;#travelling@cherkashindev&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-270-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-270-1.jpg"/></item><item><title>Декабрь подходит к концу, поэтому пора подводить итоги года, в котором было немало как хорошего,…</title><link>https://cherkashin.dev/posts/260/</link><guid isPermaLink="true">https://cherkashin.dev/posts/260/</guid><description>Декабрь подходит к концу, поэтому пора подводить итоги года, в котором было немало как хорошего, так и плохого.

✅ Начнём с хорошего:

🔥 В этом году старался доделать то, что долгое время откладывал:

вычистил небольшой техдолг на работе, который обсуждали несколько летнаписал статью о нашем опыте миграции на Реакт до...</description><pubDate>Tue, 31 Dec 2024 11:47:19 GMT</pubDate><content:encoded>&lt;p&gt;Декабрь подходит к концу, поэтому пора подводить итоги года, в котором было немало как хорошего, так и плохого.&lt;/p&gt;
&lt;p&gt;✅ Начнём с хорошего:&lt;/p&gt;
&lt;p&gt;🔥 В этом году старался доделать то, что долгое время откладывал:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вычистил небольшой техдолг на работе, который обсуждали несколько лет&lt;/li&gt;
&lt;li&gt;написал &lt;a href=&quot;https://habr.com/ru/articles/866158/&quot;&gt;статью о нашем опыте миграции на Реакт &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;дописал &lt;a href=&quot;https://www.cherkashin.dev/codereview-analyzer/&quot;&gt;тулзу для анализа код-ревью&lt;/a&gt; и подготовил внутренний доклад&lt;/li&gt;
&lt;li&gt;договорился о еженедельных созвонах для фронтендеров, чтобы шарить знания &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cherkashin.dev/&quot;&gt;перевёл блог с Jekyll на Astro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🏡 Съездил с отцом в Москву. Показать ему как она изменилась за последние 20 лет.&lt;/p&gt;
&lt;p&gt;🇮🇳 Слетал на недельный тимбилдинг в Индию. В очередной раз понял, что удалёнка — это очень удобно, но когда вы знакомы с людьми лично — ваше общение и взаимопонимание выходит на новый уровень.&lt;/p&gt;
&lt;p&gt;✈️ За год этот канал вырос в 4 раза, спасибо, что читаете 🫶&lt;/p&gt;
&lt;p&gt;Посетил конференции:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/195&quot;&gt;Teamly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/207&quot;&gt;Впервые сходил на подлодку&lt;/a&gt; и получил бесплатный билет на следующую в феврале 2025&lt;/li&gt;
&lt;li&gt;Я 💛 Frontend&lt;/li&gt;
&lt;li&gt;Я.Субботник в Москве и Питере&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Путешествия:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🇷🇺 Сочи, Москва, Питер, Липецк, Воронеж, Ростов-на-Дону&lt;/li&gt;
&lt;li&gt;🇪🇬 &lt;a href=&quot;https://t.me/cherkashindev/245&quot;&gt;Шарм,&lt;/a&gt; &lt;a href=&quot;https://t.me/cherkashindev/229&quot;&gt;Каир&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;🇮🇳 Мумбаи&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И ещё немного:
🪚 Наконец-то сделал ремонт на балконе
💪 Начал ходить в зал
🎾 30 тренировок по теннису
🇬🇧 25 уроков английского
🎙️ &lt;a href=&quot;https://habr.com/ru/articles/866158/&quot;&gt;Дал небольшое интервью&lt;/a&gt;
🏃🏼‍♂️ Пробежал ещё один полумарафон
🧑‍🏫 Провел 13 ментор сессий
💻 &lt;a href=&quot;https://t.me/cherkashindev/229&quot;&gt;Чуть не потерять ноут в Каире&lt;/a&gt;
🚀 Летел 2 дня из Каира в Мумбаи с 2-мя пересадками
💎 &lt;a href=&quot;https://t.me/cherkashindev/225&quot;&gt;Переехал с Notion на Obsidian&lt;/a&gt;
🎭 Сходил на Лебединое Озеро в Москве
🥃 Прошелся по барам в Питере&lt;/p&gt;
&lt;p&gt;❌ Не обошлось и без ложки дёгтя:&lt;/p&gt;
&lt;p&gt;🕵️‍♂️ Первое написанное заявление в прокуратуру. Оказывается у нас в стране очень просто взять деньги и не возвращать. Достаточно просто не иметь имущества, чтобы с тебя нечего было взять.&lt;/p&gt;
&lt;p&gt;🚨 Шокирующие события августа и участившиеся сирены за окном. Нашел фото рабочего места в коридоре.&lt;/p&gt;
&lt;p&gt;Самое главное, чему научил 2024 год — ценить то, что у нас есть. То что кажется данностью, очень просто может исчезнуть.&lt;/p&gt;
&lt;p&gt;Всех с наступающим новым годом! 🎉 🎄❄️☃️🌨️&lt;/p&gt;
&lt;p&gt;#newyear #итогигода&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-260-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-260-1.jpg"/></item><item><title>Когда говорят об истории JavaScript часто упоминают, каким незаменимым он был при украшении сайтов…</title><link>https://cherkashin.dev/posts/259/</link><guid isPermaLink="true">https://cherkashin.dev/posts/259/</guid><description>Когда говорят об истории JavaScript часто упоминают, каким незаменимым он был при украшении сайтов снежинками ❄️ в канун Нового года 🎄.

А между тем, Новый год уже на следующей неделе, поэтому пора поспешить и принарядить свои сайты.

🗣️ Я попросил ChatGPT:

на основе существующего логотипа сгенерировать новогоднийна...</description><pubDate>Mon, 23 Dec 2024 10:02:01 GMT</pubDate><content:encoded>&lt;p&gt;Когда говорят об истории JavaScript часто упоминают, каким незаменимым он был при украшении сайтов снежинками ❄️ в канун Нового года 🎄.&lt;/p&gt;
&lt;p&gt;А между тем, Новый год уже на следующей неделе, поэтому пора поспешить и принарядить свои сайты.&lt;/p&gt;
&lt;p&gt;🗣️ Я попросил ChatGPT:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;на основе существующего логотипа сгенерировать новогодний&lt;/li&gt;
&lt;li&gt;написать код для реализации тех самых снежинок&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я сравнил код ChatGPT с кодом из статьи Доки “&lt;a href=&quot;https://doka.guide/recipes/snow/&quot;&gt;Снежинки&lt;/a&gt;” от &lt;a href=&quot;https://t.me/frontend_kulichi&quot;&gt;Алёны Батицкой&lt;/a&gt;, взял от обоих решений лучшее, и &lt;a href=&quot;https://www.cherkashin.dev/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=telegram_post_259&amp;#x26;utm_term=snowfall&quot;&gt;вот что получилось&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;✍️ Кратко о реализации:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Берём символы Unicode для снежинок — ❄ ❅ ❆&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;В разметке создаём нужное количество снежинок — у меня 120&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Каждая снежинка состоит из 2-х частей&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;контейнер — для анимации падения&lt;/li&gt;
&lt;li&gt;сама снежинка — для анимации поворота&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Все снежинки кладём в один контейнер и выставляем ему &lt;code&gt;pointer-events: none&lt;/code&gt;, чтобы не мешать взаимодействию со страницей&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Контейнеру выставляем &lt;code&gt;flex-direction: row&lt;/code&gt;, чтобы равномерно распределить снежинки по экрану&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Начальное и конечное положения снежинок находится немного за пределами экрана, чтобы они плавно появлялись и исчезали&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Выставляем случайным образом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;размер снежинок (`font-size`) — от 0.7em до 1.5em&lt;/li&gt;
&lt;li&gt;длительность анимации падения — от 10 до 30 секунд&lt;/li&gt;
&lt;li&gt;задержку анимации — от 1 до 30 секунд&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Задержка анимации нужна, чтобы снежинки падали постепенно&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Выставляем разные цвета снежинок&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Исходники &lt;a href=&quot;https://github.com/acherkashin/acherkashin.github.io/blob/main/src/components/Snowfall.astro&quot;&gt;здесь&lt;/a&gt; 💾&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Демо &lt;a href=&quot;https://www.cherkashin.dev/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=telegram_post_259&amp;#x26;utm_term=demo&quot;&gt;здесь&lt;/a&gt; 🖥️&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;
&lt;p&gt;#newyear #blog&lt;/p&gt;</content:encoded></item><item><title>Я давно не рекомендовал ничего почитать, но эта короткая статья не оставила меня равнодушным.</title><link>https://cherkashin.dev/posts/258/</link><guid isPermaLink="true">https://cherkashin.dev/posts/258/</guid><description>Я давно не рекомендовал ничего почитать, но эта короткая статья не оставила меня равнодушным.

&quot;Всего несколько строк CSS для плавных переходов между страницами&quot;

перевод на хабреоригинал

Я много раз слышал, про View Transitions API и о том, что теперь можно настраивать анимации перехода между страницами, но никогда н...</description><pubDate>Fri, 20 Dec 2024 07:42:01 GMT</pubDate><content:encoded>&lt;p&gt;Я давно не рекомендовал ничего почитать, но эта короткая статья не оставила меня равнодушным.&lt;/p&gt;
&lt;p&gt;“Всего несколько строк CSS для плавных переходов между страницами”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/ruvds/articles/865580/&quot;&gt;перевод на хабре&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2024/3/&quot;&gt;оригинал &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я много раз слышал, про View Transitions API и о том, что теперь можно настраивать анимации перехода между страницами, но никогда не пробовал.&lt;/p&gt;
&lt;p&gt;В статье автор предлагает сделать переходы между страницами плавными с помощью одной строчки кода.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;@view-transition&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { navigation: auto; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Чтобы понять о чём говорит автор просто посмотрите прикреплённое видео:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2024/3&quot;&gt;или откройте оригинал статьи и воспроизведите видео&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;или же &lt;a href=&quot;https://www.cherkashin.dev/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=telegram_post_258&amp;#x26;utm_term=open-blog&quot;&gt;откройте мой блог&lt;/a&gt; и попробуйте перейти на одну из последних статей&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В SPA приложениях также есть возможность использовать View Transitions API. Можете посмотреть демки в статье: &lt;a href=&quot;https://habr.com/ru/articles/745708/&quot;&gt;“Введение в View Transitions API”.&lt;/a&gt;  Анимация реализуется с помощью &lt;code&gt;startViewTransition&lt;/code&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;startViewTransition&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; updateTheDOMSomehow&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;При использовании View Transitions API происходит следующее:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;делается снимок текущего состояния страницы&lt;/li&gt;
&lt;li&gt;выполняется обновление DOM (&lt;code&gt;updateTheDOMSomehow&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;делается снимок нового состояния страницы&lt;/li&gt;
&lt;li&gt;переход между этими состояниями анимируется с помощью дефолтного плавного затухания или с помощью кастомной анимации&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Более сложные примеры  можно узнать отсюда:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.smashingmagazine.com/2023/12/view-transitions-api-ui-animations-part1/&quot;&gt;The View Transitions API And Delightful UI Animations (Part 1)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.smashingmagazine.com/2024/01/view-transitions-api-ui-animations-part2/&quot;&gt;The View Transitions API And Delightful UI Animations (Part 2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Dud0DozVwvo&amp;#x26;ab_channel=%D0%92%D0%B8%D0%B4%D0%B5%D0%BE%D1%81%D0%BC%D0%B5%D1%80%D0%BE%D0%BF%D1%80%D0%B8%D1%8F%D1%82%D0%B8%D0%B9%7Bspeach%21&quot;&gt;Никита Дубко. По-настоящему красивые переходы средствами браузера&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для блогов на Astro:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/en/guides/view-transitions/&quot;&gt;Документация View Transitions в доке Astro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Как починить темную и светлую темы после внедрения view transitions — &lt;a href=&quot;https://www.reddit.com/r/webdev/comments/16iu3uf/how_do_i_get_dark_theme_working_when_using_view/&quot;&gt;читать тут&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend #fridayreading&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded></item><item><title>В прошлом году я каким-то образом умудрился написать 6 статей. В этом же с трудом нашел силы на…</title><link>https://cherkashin.dev/posts/257/</link><guid isPermaLink="true">https://cherkashin.dev/posts/257/</guid><description>В прошлом году я каким-то образом умудрился написать 6 статей. В этом же с трудом нашел силы на одну — Как мы мигрируем с JQuery на React.

Во время миграции мы столкнулись со многими трудностями, поэтому я решил описать наш подход в виде статьи.

Из статьи вы узнаете:

1️⃣ как мы писали код до React
2️⃣ какой подход м...</description><pubDate>Tue, 17 Dec 2024 07:15:34 GMT</pubDate><content:encoded>&lt;p&gt;В прошлом году я каким-то образом умудрился написать 6 статей. В этом же с трудом нашел силы на одну — &lt;a href=&quot;https://habr.com/ru/articles/866158/&quot;&gt;Как мы мигрируем с JQuery на React&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Во время миграции мы столкнулись со многими трудностями, поэтому я решил описать наш подход в виде статьи.&lt;/p&gt;
&lt;p&gt;Из статьи вы узнаете:&lt;/p&gt;
&lt;p&gt;1️⃣ как мы писали код до React
2️⃣ какой подход мы выбрали для миграции
3️⃣ как нам мешали пространства имён тайпскрипта
4️⃣ как конфигурировали webpack
5️⃣ что делать, если нужно использовать легаси код внутри React
6️⃣ как мы писали кастомный генератор типов
7️⃣ почему выбрали Zustand для управления состоянием&lt;/p&gt;
&lt;p&gt;Обязательно переходите и читайте.
Буду признателен если сделаете репост или проголосуете за статью на Хабре, это поможет её продвижению 🔥. Кто-то поставил минус за обложку статьи, так что спасайте 😄&lt;/p&gt;
&lt;p&gt;#article #react #habr&lt;/p&gt;</content:encoded></item><item><title>Программа на эти выходные. Попал сразу на оба мероприятия оффлайн 🔥.</title><link>https://cherkashin.dev/posts/255/</link><guid isPermaLink="true">https://cherkashin.dev/posts/255/</guid><description>Программа на эти выходные. Попал сразу на оба мероприятия оффлайн 🔥.

#conference</description><pubDate>Thu, 12 Dec 2024 09:27:28 GMT</pubDate><content:encoded>&lt;p&gt;Программа на эти выходные. Попал сразу на оба мероприятия оффлайн 🔥.&lt;/p&gt;
&lt;p&gt;#conference&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-255-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-255-1.jpg"/></item><item><title>Как мы мигрируем с JQuery на React</title><link>https://cherkashin.dev/articles/migration-from-jquery-to-react/</link><guid isPermaLink="true">https://cherkashin.dev/articles/migration-from-jquery-to-react/</guid><description>Вокруг все говорят о серверных компонентах реакта, о серверном рендеринге, и разных новшествах в мире фронтенде. Как будто JQuery в один миг взял и исчез. Несмотря ни на что он всё ещё остаётся самой популярной библиотекой 😅.</description><pubDate>Tue, 10 Dec 2024 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/migration-from-jquery-to-react/jquery-in-2024-meme.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/migration-from-jquery-to-react/jquery-in-2024-meme.png"/></item><item><title>В прошлом году мы с женой летали в Стамбул, но запомнил я от силы процентов 10. Фото есть, но…</title><link>https://cherkashin.dev/posts/245/</link><guid isPermaLink="true">https://cherkashin.dev/posts/245/</guid><description>В прошлом году мы с женой летали в Стамбул, но запомнил я от силы процентов 10. Фото есть, но хочется запомнить и свои ощущения. В этот раз в Египте я стал делать заметки, и вот дошли руки собрать из них что-то читаемое.

Про почти потерянный ноут вы уже читали 😅.

🧳 Подготовка

Отпуск был запланирован на конец сентя...</description><pubDate>Thu, 05 Dec 2024 12:57:03 GMT</pubDate><content:encoded>&lt;p&gt;В прошлом году мы с женой летали в Стамбул, но запомнил я от силы процентов 10. Фото есть, но хочется запомнить и свои ощущения. В этот раз в Египте я стал делать заметки, и вот дошли руки собрать из них что-то читаемое.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev/229&quot;&gt;Про почти потерянный ноут вы уже читали&lt;/a&gt; 😅.&lt;/p&gt;
&lt;p&gt;🧳 &lt;strong&gt;Подготовка&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Отпуск был запланирован на конец сентября. Обычно на море мне становится скучно через пару дней (но не в этот раз!), поэтому я стараюсь выехать на несколько дней в город.&lt;/p&gt;
&lt;p&gt;Решили ехать в:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Шарм-эль-Шейх&lt;/li&gt;
&lt;li&gt;и Каир&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;🛩️ План: Москва — Шарм — Каир — Москва&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Билеты “Москва — Шарм” на двоих - 100к 😳. Тур туда/обратно — столько же (без отеля). Поэтому мы решили взять тур и отказаться от обратных билетов. Была небольшая надежда, что туроператор вернёт деньги. Этот вариант выгорел пару лет назад в Турции, но тут систему надурить не удалось.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Итог:&lt;/strong&gt; тур в Шарм, билеты до Каира и Москвы отдельно.&lt;/p&gt;
&lt;p&gt;🙏 &lt;strong&gt;Ожидания&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я старался не строить завышенных ожиданий от поездки, особенно после того как начитался отзывов интернетных экспертов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Одни утверждали, что все будут стараться тебя на**ать (и были не далеки от истины)&lt;/li&gt;
&lt;li&gt;Вторые говорили, что сервис — отстой, а если не оставлять чаевые — то и “под дверью нагадят”.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🚧 &lt;strong&gt;Если кратко&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Обслуживание — хорошее, под дверью пусто&lt;/li&gt;
&lt;li&gt;Море — пушка, маска для снорклинга — обязательно&lt;/li&gt;
&lt;li&gt;Шарм — класс&lt;/li&gt;
&lt;li&gt;Манго и еда — шик&lt;/li&gt;
&lt;li&gt;Пиво — пойдёт&lt;/li&gt;
&lt;li&gt;Вино — ужас&lt;/li&gt;
&lt;li&gt;Торговцы — наглые&lt;/li&gt;
&lt;li&gt;Для такси — &lt;a href=&quot;https://indrive.com/&quot;&gt;InDrive&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🏝️ &lt;strong&gt;Шарм&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Добрались до отеля мы рано утром. Носильщик донёс чемодан до номера, собрался уходить, но я его остановил и всё-таки дал доллар. Ну на всякий случай.&lt;/p&gt;
&lt;p&gt;Немного отдохнув, мы собрали вещи и пошли на пляж. Жена провела мне инструктаж, мол “рыб не трогай, к кораллам не лезь”. Я надел маску и сразу полез в воду.&lt;/p&gt;
&lt;p&gt;Открыв глаза под водой, я увидел множество рыб вокруг себя, растерялся и попытался отплыть от них в сторону. Ну и конечно же сразу влупился ногой об коралл. Я вылез на пирс, мне обработали ногу. Через 2 дня она была размером с голову, но об этом в другой раз.&lt;/p&gt;
&lt;p&gt;Товарищи говорили мне, что стоит хоть раз съездить на Красное море, и они были правы. Вода — очень солёная, ты совсем не тонешь, просто лежишь на воде, дышишь через трубку и наблюдаешь за подводным миром часами напролёт.&lt;/p&gt;
&lt;p&gt;В один день море было особенно чудесное — такого количества рыб мы ещё не видели. Я лежал на воде, глазел на этих рыб и впервые за долгое время ощутил, что время не важно, я вне времени, я просто о нем не думаю, без понятия сколько времени прошло, ведь это не важно.&lt;/p&gt;
&lt;p&gt;В общем, море — лучшее воспоминание, которое у меня осталось.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🚶 Выходим из отеля — такси и продавцы&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Вызвали Такси. Цена в приложении — 105 фунтов. По совету интернетных экспертов уточняю цену до поездки, на что таксист говорит, что это копейки и поедет только за 150. Ок, сторговались на 120.&lt;/p&gt;
&lt;p&gt;Едем минут 10, и таксист говорит:
— Слушай, Мухамед (он) - хороший, машина - хороший, ставь мне 5 звёзд&lt;br&gt;
— Да, конечно, обязательно поставлю (нет)
— Ставь, сейчас!&lt;/p&gt;
&lt;p&gt;Я немного офигел от наглости, InDrive похоже тоже офигел, заглючил и отрубился.&lt;/p&gt;
&lt;p&gt;Доезжаем до Наама Бей. К нам подходит мужчина и говорит, что ещё очень рано и всё закрыто. Мы спросили, где находится аптека и он предложил нас проводить. Слово за слово, и он заводит нас в лавку с маслами. Это — его лавка, он начинает нам показывать сколько у него отзывов, мол купите что-нибудь и идите в аптеку, или хотя бы отзыв оставьте.&lt;/p&gt;
&lt;p&gt;Я офигел от наглости 2 раз за 10 минут и игнорил торговцев весь отпуск 😄.&lt;/p&gt;
&lt;p&gt;🛬 &lt;strong&gt;Вылет в Каир&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Мы отлично отдохнули в Шарме и поехали в Аэропорт.&lt;/p&gt;
&lt;p&gt;Здесь меня удивило, что на входе была огромная очередь на досмотр, а рядом ещё одна небольшая очередь для тех, кто дал на лапу, чтобы пройти без очереди.&lt;/p&gt;
&lt;p&gt;Дать на лапу тебя не навязчиво попросят прямо сотрудники аэропорта, которые очень хотят, чтобы ты сэкономил 10 минут фунтов за 300. В остальном — всё как в обычном аэропорте.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;На сегодня всё. Шукран, что дочитали 👋.
А где вы провели последний отпуск❓&lt;/p&gt;
&lt;p&gt;#travelling&lt;/p&gt;
&lt;p&gt;@cherkalexander&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-245-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-245-1.jpg"/></item><item><title>В прошлом месяце я писал, что постепенно пытаюсь оживить свой блог и переписываю его на Astro.</title><link>https://cherkashin.dev/posts/244/</link><guid isPermaLink="true">https://cherkashin.dev/posts/244/</guid><description>В прошлом месяце я писал, что постепенно пытаюсь оживить свой блог и переписываю его на Astro.

Обычно я закапываюсь, чтобы довести что-то до конца. Например, если это пост или статья — нужно посмотреть 100500 видео и статей, чтобы во всём разобраться.

В этот раз я подумал, что &quot;Лучшее — враг хорошего.&quot; и решил, что д...</description><pubDate>Mon, 02 Dec 2024 08:01:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev/239&quot;&gt;В прошлом месяце&lt;/a&gt; я писал, что постепенно пытаюсь &lt;a href=&quot;https://cherkashin.dev/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=telegram_post&amp;#x26;utm_term=rewrite-blog&quot;&gt;оживить свой блог&lt;/a&gt; и переписываю его на Astro.&lt;/p&gt;
&lt;p&gt;Обычно я закапываюсь, чтобы довести что-то до конца. Например, если это пост или статья — нужно посмотреть 100500 видео и статей, чтобы во всём разобраться.&lt;/p&gt;
&lt;p&gt;В этот раз я подумал, что “Лучшее — враг хорошего.” и решил, что для блога будет достаточно MVP:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Перенёс все статьи&lt;/li&gt;
&lt;li&gt;Добавил секцию с проектами&lt;/li&gt;
&lt;li&gt;Поправил стили&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Далее в планах:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Прикрутить комментарии&lt;/li&gt;
&lt;li&gt;Опубликовать CV&lt;/li&gt;
&lt;li&gt;Реализовать кнопку Share&lt;/li&gt;
&lt;li&gt;Добавить какую-нибудь пасхалку в консоль, куда ж без этого. Есть идеи? 😄&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Кстати, если вы переписываете блог, не забудьте убедиться, что ссылки на ваши старые статьи работают. Например, у Jekyll и Astro — разные форматы URL, поэтому чтобы старые ссылки не сломались нужно &lt;a href=&quot;https://docs.astro.build/en/guides/routing/#configured-redirects&quot;&gt;использовать редиректы&lt;/a&gt;:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;//astro.config.mjs&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; defineConfig&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; redirects: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;  &apos;/old-page&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;/new-page&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;})&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;P.S. Если знаете, как прикрутить комментарии и реакции для блога — расскажите в комментариях 👇.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cherkashin.dev/?utm_source=telegram&amp;#x26;utm_medium=owned&amp;#x26;utm_campaign=telegram_post&amp;#x26;utm_term=blog-link&quot;&gt;Ссылка на блог&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;
&lt;p&gt;#блог #astro&lt;/p&gt;</content:encoded></item><item><title>Сейчас темп жизни такой, что на всё не хватает времени. И чтобы сэкономить время на уборке, в…</title><link>https://cherkashin.dev/posts/243/</link><guid isPermaLink="true">https://cherkashin.dev/posts/243/</guid><description>Сейчас темп жизни такой, что на всё не хватает времени. И чтобы сэкономить время на уборке, в прошлом году я раскошелился и решил заменить свой старый робот-пылесос Xiaomi (который штурмовал каждую неровность) на новый, более современный.

После просмотра кучи обзоров остановился на DreamBot L10s Ultra. Если кратко о е...</description><pubDate>Thu, 21 Nov 2024 08:39:41 GMT</pubDate><content:encoded>&lt;p&gt;Сейчас темп жизни такой, что на всё не хватает времени. И чтобы сэкономить время на уборке, в прошлом году я раскошелился и решил заменить свой старый робот-пылесос Xiaomi (который штурмовал каждую неровность) на новый, более современный.&lt;/p&gt;
&lt;p&gt;После просмотра кучи обзоров остановился на DreamBot L10s Ultra. Если кратко о его использовании:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;чистой воды налил&lt;/li&gt;
&lt;li&gt;грязную вылил&lt;/li&gt;
&lt;li&gt;мешок для мусора вставил (раз в пол года)
а дальше он все сам:&lt;/li&gt;
&lt;li&gt;воды наберет&lt;/li&gt;
&lt;li&gt;мусор выгрузит&lt;/li&gt;
&lt;li&gt;даже тряпки сам помоет и высушит.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем, чая навели, пылесос включили и пошли на стендап.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;А если вы вдруг давно думали сменить работу, то чтобы сэкономить вам время, &lt;strong&gt;я принес вакансию&lt;/strong&gt; от своего земляка и тёзки в международную компанию Hoodies.&lt;/p&gt;
&lt;p&gt;О продукте:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Продукт для мониторинга упоминания компаний в соц сетях. &lt;/li&gt;
&lt;li&gt;Задача продукта – с помощью AI помочь бизнесу упростить процесс маркетинговых исследований для понимания и управления репутацией своих продуктов.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;О позиции:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;требуется Senior Frontend разработчик &lt;/li&gt;
&lt;li&gt;стек — React, TypeScript, Next.js&lt;/li&gt;
&lt;li&gt;опыт разработки интерактивных дашбордов&lt;/li&gt;
&lt;li&gt;зарплата ~$5000&lt;/li&gt;
&lt;li&gt;удаленка, гибкий график&lt;/li&gt;
&lt;li&gt;разные варианты трудоустройства&lt;/li&gt;
&lt;li&gt;хороший английский&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Полное описание вакансии и как откликнуться — в комментарии к посту, если что-то непонятно пишите в личку @cherkalexander.&lt;/p&gt;
&lt;p&gt;#about_me  #вакансия&lt;/p&gt;</content:encoded></item><item><title>return Promise 🆚 return await Promise</title><link>https://cherkashin.dev/posts/241/</link><guid isPermaLink="true">https://cherkashin.dev/posts/241/</guid><description>return Promise 🆚 return await Promise

Что будет выведено в консоль?

async function test1() {
    console.log(&apos;start-1&apos;);
    return Promise.resolve();
}

async function test2() {
    console.log(&apos;start-2&apos;);
    return await Promise.resolve();
}

test1().then(() =&gt; console.log(&apos;done-1&apos;));
test2().then(() =&gt; console.l...</description><pubDate>Mon, 18 Nov 2024 07:55:38 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;return Promise 🆚 return await Promise&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Что будет выведено в консоль?&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; test1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;start-1&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; test2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;start-2&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;test1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;done-1&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;test2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;done-2&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;end&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;
&lt;p&gt;#typescript&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-241-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-241-1.jpg"/></item><item><title>// @ts-nocheck</title><link>https://cherkashin.dev/posts/240/</link><guid isPermaLink="true">https://cherkashin.dev/posts/240/</guid><description>// @ts-nocheck

Помню, когда я только начал изучать TypeScript, мне часто попадалась фраза: &quot;TypeScript — это надмножество JavaScript, и любой корректный JavaScript-код является также корректным TypeScript-кодом&quot;. В общем, если надоел JavaScript — меняешь расширение файла с .js на .ts и радуешься жизни (или нет).

Вчер...</description><pubDate>Fri, 15 Nov 2024 08:23:01 GMT</pubDate><content:encoded>&lt;p&gt;// @ts-nocheck&lt;/p&gt;
&lt;p&gt;Помню, когда я только начал изучать TypeScript, мне часто попадалась фраза: “TypeScript — это надмножество JavaScript, и любой корректный JavaScript-код является также корректным TypeScript-кодом”. В общем, если надоел JavaScript — меняешь расширение файла с &lt;code&gt;.js&lt;/code&gt; на &lt;code&gt;.ts&lt;/code&gt; и радуешься жизни (или нет).&lt;/p&gt;
&lt;p&gt;Вчера поздним вечером я копался в нашем легаси, некоторому коду лет 10, а то и больше. И я вспомнил, как лет 6 назад менял расширение этих файлов на &lt;code&gt;.ts&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;У нас на проекте тогда уже использовался TypeScript, но был и пласт легаси на чистом JavaScript. Я попробовал переименовать их в &lt;code&gt;.ts&lt;/code&gt;, и тут весь файл стал огненно красным. Не всё так просто, как говорили эксперты.&lt;/p&gt;
&lt;p&gt;Но в версии 3.7 TypeScript появилась директива &lt;code&gt;// @ts-nocheck&lt;/code&gt;. Просто добавляешь её в начале файла, и проверка типов отключается, и можно постепенно мигрировать на TS.&lt;/p&gt;
&lt;p&gt;Потом переписывать их на TS, конечно же, никто не собирался 😄&lt;/p&gt;
&lt;p&gt;#typescript&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-240-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-240-1.jpg"/></item><item><title>Я уже года 4 плачу за свой домен cherkashin.dev, где хостится мой мертвый и убогий блог, который я…</title><link>https://cherkashin.dev/posts/239/</link><guid isPermaLink="true">https://cherkashin.dev/posts/239/</guid><description>Я уже года 4 плачу за свой домен &lt;cherkashin.dev&gt;, где хостится мой мертвый и убогий блог, который я сделал во время ковида, и с тех пор ни разу не трогал. В то время я не слышал про 11ty, а Astro ещё не появился. ChatGPT тоже ещё не было, поэтому — я погуглил, поспрашивал знакомых и взял Jekyll.

GitHub Pages, насколь...</description><pubDate>Thu, 07 Nov 2024 10:03:01 GMT</pubDate><content:encoded>&lt;p&gt;Я уже года 4 плачу за свой домен &amp;#x3C;cherkashin.dev&gt;, где хостится мой мертвый и убогий блог, который я сделал во время ковида, и с тех пор ни разу не трогал. В то время я не слышал про &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty&lt;/a&gt;, а &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; ещё не появился. ChatGPT тоже ещё не было, поэтому — я погуглил, поспрашивал знакомых и взял &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;GitHub Pages, насколько я помню, &lt;a href=&quot;https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll&quot;&gt;неплохо дружат&lt;/a&gt; с Jekyll, я взял какой-то простенький шаблон для быстрого старта и опубликовал блог. Но Jekyll написан на Ruby, а это значит, что придётся постоянно сталкиваться с ним для настройки и билда блога, поэтому я быстро забил. &lt;/p&gt;
&lt;p&gt;Этим летом я сходил на конфу подлодки и узнал про Astro. &lt;a href=&quot;https://github.com/nicdun/astro-tech-blog&quot;&gt;Нашёл темплейт&lt;/a&gt; и потихоньку мигрирую. На скрине текущее состояние блога.&lt;/p&gt;
&lt;p&gt;Кстати, если вы используете Astro и вам нужна аналитика, то @xufostation есть &lt;a href=&quot;https://github.com/ufocoder/astro-yandex-metrika&quot;&gt;Astro плагин для Яндекс Метрики&lt;/a&gt;. У плагина пока мало звезд — поэтому давайте исправим это. Нам не сложно, а автору будет приятно.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ufocoder/astro-yandex-metrika&quot;&gt;https://github.com/ufocoder/astro-yandex-metrika&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#блог #astro&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-239-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-239-1.jpg"/></item><item><title>✉️ Реализация инбокса в Obsidian с помощью Apple Shortcuts</title><link>https://cherkashin.dev/posts/236/</link><guid isPermaLink="true">https://cherkashin.dev/posts/236/</guid><description>✉️ Реализация инбокса в Obsidian с помощью Apple Shortcuts

Те, кто давно на меня подписан могут помнить, что я рассказывал как настроить Inbox для Notion с помощью Apple Shortcuts (тут и тут).

Если кратко — Apple Shortcuts позволяет делать автоматизации, которые, например, можно запускать нажатием на ярлык. Для Notio...</description><pubDate>Thu, 31 Oct 2024 09:01:01 GMT</pubDate><content:encoded>&lt;p&gt;✉️ &lt;strong&gt;Реализация инбокса в Obsidian с помощью Apple Shortcuts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Те, кто давно на меня подписан могут помнить, что я рассказывал как настроить Inbox для Notion с помощью Apple Shortcuts &lt;a href=&quot;https://t.me/cherkashindev/43&quot;&gt;(тут&lt;/a&gt; и &lt;a href=&quot;https://t.me/cherkashindev/103&quot;&gt;тут).&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Если кратко — Apple Shortcuts позволяет делать автоматизации, которые, например, можно запускать нажатием на ярлык. Для Notion автоматизация была простая:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Показывается текстовое поле&lt;/li&gt;
&lt;li&gt;Мы вводим свою заметку&lt;/li&gt;
&lt;li&gt;Вызывается API Notion и заметка добавляется в базу данных Inbox&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Когда я начал мигрировать на Obsidian, всё это конечно перестало работать. Казалось, что придётся делать заметки в Apple Notes а затем ручками переносить всё в Obsidian.&lt;/p&gt;
&lt;p&gt;Но после того, как настроил интеграцию Obsidian с GitHub понял, что можно добавлять заметки напрямую в GitHub репозиторий через &lt;a href=&quot;https://docs.github.com/en/rest?apiVersion=2022-11-28&quot;&gt;GitHub API.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;И это сработало, пришлось лишь сильно поменять реализацию шортката. Теперь это работает так:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Показывается текстовое поле&lt;/li&gt;
&lt;li&gt;Мы вводим текст заметки&lt;/li&gt;
&lt;li&gt;Он кодируется в base64, так требует GitHub API&lt;/li&gt;
&lt;li&gt;Получаем текущую дату, она будет являться именем заметки&lt;/li&gt;
&lt;li&gt;Формируем URL для создания файла в репозитории —  &lt;code&gt;https://api.github.com/repos/{owner}/{repo}/contents/{path}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Отправляем запрос, предварительно нужно сгенерировать &lt;a href=&quot;https://github.com/settings/personal-access-tokens/new&quot;&gt;GitHub Access Token.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;При открытии Obsidian сделает pull из репозитория и заметка отобразится в папке Inbox, или можно сделать pull вручную&lt;/li&gt;
&lt;li&gt;Готово 🚀&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Позже поделюсь ссылкой на готовый шорткат, если кому-то нужно.&lt;/p&gt;
&lt;p&gt;#obsidian #nocode #planning&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-237-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-237-1.jpg"/></item><item><title>Этот самурай незаметно пробрался в квартиру прошлой ночью. К счастью, мы с женой не пострадали,…</title><link>https://cherkashin.dev/posts/235/</link><guid isPermaLink="true">https://cherkashin.dev/posts/235/</guid><description>Этот самурай незаметно пробрался в квартиру прошлой ночью. К счастью, мы с женой не пострадали, чего нельзя сказать о старом кресле ...

#workingplace

@cherkashindev</description><pubDate>Mon, 28 Oct 2024 08:03:01 GMT</pubDate><content:encoded>&lt;p&gt;Этот самурай незаметно пробрался в квартиру прошлой ночью. К счастью, мы с женой не пострадали, чего нельзя сказать о старом кресле …&lt;/p&gt;
&lt;p&gt;#workingplace&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-235-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-235-1.jpg"/></item><item><title>Выходной в Пятницу</title><link>https://cherkashin.dev/posts/234/</link><guid isPermaLink="true">https://cherkashin.dev/posts/234/</guid><description>Выходной в Пятницу

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

В итоге:

пересмотрел пару серий Игры престолов. Одичалые штурмуют стену, а Тириона Ланнистера хотят казнить.разобрал (почти) рабочий стол на ноутеудалил всякого мусора на 40...</description><pubDate>Fri, 18 Oct 2024 16:47:35 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Выходной в Пятницу&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Решил приблизить конец недели и взял сегодня выходной, чтобы просто заняться накопившимися бытовыми делами и тупо отдохнуть.&lt;/p&gt;
&lt;p&gt;В итоге:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;пересмотрел пару серий Игры престолов. Одичалые штурмуют стену, а Тириона Ланнистера хотят казнить.&lt;/li&gt;
&lt;li&gt;разобрал (почти) рабочий стол на ноуте&lt;/li&gt;
&lt;li&gt;удалил всякого мусора на 40 Гб&lt;/li&gt;
&lt;li&gt;съездил на теннис, зная, что мне не нужно мчаться на работу&lt;/li&gt;
&lt;li&gt;разобрал чеки и справки, которые лежали пару месяцев в ящике&lt;/li&gt;
&lt;li&gt;записался в больницу&lt;/li&gt;
&lt;li&gt;выставил ненужный хлам на авито&lt;/li&gt;
&lt;li&gt;а ещё нашел #obsidian  &lt;a href=&quot;https://github.com/SkepticMystic/advanced-cursors&quot;&gt;плагин 🚀, который&lt;/a&gt; умеет в мультикурсор, прям как VS Code (&lt;code&gt;CMD&lt;/code&gt;/CTRL&lt;code&gt; + D&lt;/code&gt;), нужно только настроить горячие клавиши&lt;/li&gt;
&lt;li&gt;а теперь пойду ||забью кальян||, пятница же&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Жаль, что каждую пятницу так делать не прокатит 😅.&lt;/p&gt;
&lt;p&gt;P.S. Ходят слухи, что некоторые компании практикуют 4-х дневную рабочую неделю, вы работали в таких? Или может хотя бы слышали? ||Куда слать резюме? 😄||&lt;/p&gt;
&lt;p&gt;UPD: ссылку на плагин добавил&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded></item><item><title>Отдельная страница для задач в Обсидиан</title><link>https://cherkashin.dev/posts/231/</link><guid isPermaLink="true">https://cherkashin.dev/posts/231/</guid><description>Отдельная страница для задач в Обсидиан

В 🇯🇵 Notion мне всегда очень нравилось, что каждая запись в базе - это отдельная страница, которая может содержать что угодно - от простых заметок, до вложенных баз или таблиц.

Я использовал Notion, как менеджер задач, и эта возможность была критически важной для меня - работ...</description><pubDate>Wed, 16 Oct 2024 08:00:26 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Отдельная страница для задач в Обсидиан&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В 🇯🇵 Notion мне всегда очень нравилось, что каждая запись в базе - это отдельная страница, которая может содержать что угодно - от простых заметок, до вложенных баз или таблиц.&lt;/p&gt;
&lt;p&gt;Я использовал Notion, как менеджер задач, и эта возможность была критически важной для меня - работая над сложными задачами, я всегда делаю заметки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;разбиваю на подзадачи&lt;/li&gt;
&lt;li&gt;записываю нюансы, на которые я наткнулся&lt;/li&gt;
&lt;li&gt;помечаю, какие тесты необходимо написать&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Хотя в обсидиан это не поддерживается из коробки, но всё же достаточно легко реализуется:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Для задач использую &lt;a href=&quot;https://publish.obsidian.md/tasks/Introduction&quot;&gt;obsidian-tasks&lt;/a&gt; плагин, по сути это просто ToDo лист&lt;/li&gt;
&lt;li&gt;Если нужно сделать много записей по задаче или приложить скриншоты - то просто превращаем задачу в ссылку на заметку&lt;/li&gt;
&lt;li&gt;Оборачиваем задачу в Wikilink &lt;code&gt;[[]]&lt;/code&gt; и нажимаем на неё, заметка с именем задачи создастся автоматически&lt;/li&gt;
&lt;li&gt;Заметка создастся в стандартной папке для заметок, папку можно задать в &lt;code&gt;Settings =&gt; Files and links =&gt; Folder to create new notes in.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#obsidian #notion&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-231-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-231-1.jpg"/></item><item><title>Пока я Индии поедаю сабудану и досу, мне в Курск пришла книга &quot;Мама, Я тимлид!&quot; от Жени Черкасова.…</title><link>https://cherkashin.dev/posts/230/</link><guid isPermaLink="true">https://cherkashin.dev/posts/230/</guid><description>Пока я Индии поедаю сабудану и досу, мне в Курск пришла книга &quot;Мама, Я тимлид!&quot; от Жени Черкасова. Я конечно не тимлид, но книжку обязательно прочитаю.

Женя ведёт ламповый и очень уютный канал о личной и командной эффективности. Вот некоторые из моих любимых постов:

Готовься к увольнению с первого дняКак всё успетьСк...</description><pubDate>Wed, 02 Oct 2024 06:55:46 GMT</pubDate><content:encoded>&lt;p&gt;Пока я Индии поедаю сабудану и досу, мне в Курск &lt;a href=&quot;https://t.me/frontend_lead_mentor/675&quot;&gt;пришла книга&lt;/a&gt; “Мама, Я тимлид!” от &lt;a href=&quot;https://t.me/frontend_lead_mentor&quot;&gt;Жени Черкасова&lt;/a&gt;. Я конечно не тимлид, но книжку обязательно прочитаю.&lt;/p&gt;
&lt;p&gt;Женя ведёт ламповый и очень уютный канал о личной и командной эффективности. Вот некоторые из моих любимых постов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/frontend_lead_mentor/657&quot;&gt;Готовься к увольнению с первого дня&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/frontend_lead_mentor/648&quot;&gt;Как всё успеть&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/frontend_lead_mentor/672&quot;&gt;Сколько я заработал с блога&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/frontend_lead_mentor/680&quot;&gt;Как на самом деле строятся процессы&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А ещё Женя летает на параплане 😱, &lt;a href=&quot;https://t.me/frontend_lead_mentor/658&quot;&gt;обязательно посмотрите&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;А мне расскажите, читали ли вы книгу и как она вам.&lt;/p&gt;
&lt;p&gt;#рекомендую_канал&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-230-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-230-1.jpg"/></item><item><title>Пока я сижу в Шереметьево и жду свой задерживающийся рейс в Мумбаи, расскажу вам кринжовую историю,…</title><link>https://cherkashin.dev/posts/229/</link><guid isPermaLink="true">https://cherkashin.dev/posts/229/</guid><description>Пока я сижу в Шереметьево и жду свой задерживающийся рейс в Мумбаи, расскажу вам кринжовую историю, которая произошла со мной сегодня утром в аэропорте Каира.

Я всегда стараюсь приезжать заранее, будь то поезд, автобус или самолёт. На всякий случай, мало ли что может случиться. Всегда всё проходит нормально, а я тупо ...</description><pubDate>Thu, 26 Sep 2024 19:08:36 GMT</pubDate><content:encoded>&lt;p&gt;Пока я сижу в Шереметьево и жду свой задерживающийся рейс в Мумбаи, расскажу вам кринжовую историю, которая произошла со мной сегодня утром в аэропорте Каира.&lt;/p&gt;
&lt;p&gt;Я всегда стараюсь приезжать заранее, будь то поезд, автобус или самолёт. На всякий случай, мало ли что может случиться. Всегда всё проходит нормально, а я тупо жду на пол часа-час дольше, чем остальные, но не сегодня …&lt;/p&gt;
&lt;p&gt;Обычное утро, заказываем убер и едем в аэропорт, мы жили в районе &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%93%D0%B5%D0%BB%D0%B8%D0%BE%D0%BF%D0%BE%D0%BB%D0%B8%D1%81_%28%D0%9A%D0%B0%D0%B8%D1%80%29&quot;&gt;Гелиополис,&lt;/a&gt; поэтому доехали минут за 20. Рассчитываюсь с водителем и идём в аэропорт. Перед металлоискателями говорю жене: “Надеюсь, что мы пройдём всё очень быстро”, и тут ощущаю тревожную лёгкость - рюкзак с ноутом и российским паспортом остался на заднем сидении такси.&lt;/p&gt;
&lt;p&gt;Мысленно попрощавшись с ноутом и параллельно убеждая жену, что таксист ещё не успел его кому-то втюхать, пишу в поддержку убера. Чтобы связаться с водителем, я прошу номер телефона сотрудника аэропорта - российский номер не подходит. Спустя 10 минут попыток - связаться с таксистом так и не получилось. А Убер просит сообщить ему, если нам не получится вернуть рюкзак в течение 24 часов. Пока сотрудник аэропорта зовёт полицию - я понимаю, что придётся лететь домой без ноута и прикидываю, где купить новый макбук в Москве перед командировкой.&lt;/p&gt;
&lt;p&gt;Спустя 5 минут приходит худощавый египетский полицейский со стволом, который повторяет каждые 10 секунд, чтобы меня успокоить: “Don’t worry, I will help you. It is my job.”. Он мне напомнил брутального копа из американских фильмов. Изучив профиль таксиста, он уходит смотреть по камерам куда скрылся злоумышленник.&lt;/p&gt;
&lt;p&gt;Ещё минут через 5 жене приходит в голову шикарная идея - возможно на ноуте работает геолокация. Открываю на айфоне локатор и вижу, что мои наушники и ноут неподалёку от аэропорта, появляется небольшая надежда. Через пару минут, наушники снова оказываются на территории аэропорта - таксист вернулся. Я хочу выбежать на улицу, расцеловать таксиста вручить ему вознаграждение и наконец-то отправиться на регистрацию, но полицейский останавливает меня - нужно соблюсти бюрократические процедуры.&lt;/p&gt;
&lt;p&gt;Когда со всем разобрались, завязывается диалог с полицейским (П):&lt;/p&gt;
&lt;p&gt;Я: Как вы его нашли?
П: Это просто моя работа! “Как твои дела?” - спрашивает он на русском
Я: Очень хорошо! “Я бы сказал иначе, но не хочу материться.” - переходим обратно на английский.
П: Ты куришь? Может хочешь, что-нибудь выпить?
Я: Нет, ещё раз большое спасибо.
П: Египтяне хорошие люди, приезжайте к нам снова.
Я: Непременно.&lt;/p&gt;
&lt;p&gt;Подходим к металлоискателям, где другие “хорошие” египтяне разводят нас на 200 фунтов (400 рублей), но это уже совсем другая история.&lt;/p&gt;
&lt;p&gt;P.S. Таксист не говорил по-английски, но он несколько раз повторил “Uber, SMS”. Думаю, убер просто связался с таксистом и тот вернулся назад, а полицейский брутально присвоил всю славу себе. Но мы конечно всё равно ему благодарны.&lt;/p&gt;
&lt;p&gt;Расскажите, какие подобные истории происходили с вами? 😅&lt;/p&gt;
&lt;p&gt;#about_me #vacation&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-229-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-229-1.jpg"/></item><item><title>Кажется, кто-то узнал, что программист приехал на отдых.</title><link>https://cherkashin.dev/posts/227/</link><guid isPermaLink="true">https://cherkashin.dev/posts/227/</guid><description>Кажется, кто-то узнал, что программист приехал на отдых.

Сначала аэропорт SSH, теперь номер 11101, а дальше что?

Бустани канал, чтобы оставаться в курсе, а то мало ли что ...

#vacation</description><pubDate>Tue, 17 Sep 2024 12:13:05 GMT</pubDate><content:encoded>&lt;p&gt;Кажется, кто-то узнал, что программист приехал на отдых.&lt;/p&gt;
&lt;p&gt;Сначала аэропорт SSH, теперь номер 11101, а дальше что?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/boost/cherkashindev&quot;&gt;Бустани канал,&lt;/a&gt; чтобы оставаться в курсе, а то мало ли что …&lt;/p&gt;
&lt;p&gt;#vacation&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-227-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-227-1.jpg"/></item><item><title>⏭️ Соседние селекторы в CSS</title><link>https://cherkashin.dev/posts/226/</link><guid isPermaLink="true">https://cherkashin.dev/posts/226/</guid><description>⏭️ Соседние селекторы в CSS

Сегодня утром прилетает баг - у элемента не виден горизонтальный скрол. Случилось это из-за новой фичи - появился новый компонент, из-за чего соседний немного съехал и скрол ушёл за пределы экрана.

Тут я подумал, что в первый раз в жизни смогу использовать &quot;Родственные селекторы&quot; , чтобы п...</description><pubDate>Wed, 11 Sep 2024 08:13:48 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;⏭️ Соседние селекторы в CSS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня утром прилетает баг - у элемента не виден горизонтальный скрол. Случилось это из-за новой фичи - появился новый компонент, из-за чего соседний немного съехал и скрол ушёл за пределы экрана.&lt;/p&gt;
&lt;p&gt;Тут я подумал, что в первый раз в жизни смогу использовать “&lt;a href=&quot;https://thecode.media/selector/#:~:text=Copy-,%D0%A0%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5,-%D1%81%D0%B5%D0%BB%D0%B5%D0%BA%D1%82%D0%BE%D1%80%D1%8B&quot;&gt;Родственные селекторы&lt;/a&gt;” &lt;code&gt;~&lt;/code&gt;, чтобы пофиксить стили если оба элемента отображаются на странице:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.new-feature-element&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; ~&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; .element-with-scroll&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;     // тут фиксим стили, они применяются к .&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;element-with-scroll&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Посмотрел на разметку, понял что &lt;code&gt;.element-with-scroll&lt;/code&gt; всегда идёт непосредственно после &lt;code&gt;.new-feature-element&lt;/code&gt; поэтому можно поменять на &lt;code&gt;+&lt;/code&gt;:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.new-feature-element&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; .element-with-scroll&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;     // тут фиксим стили, они применяются к .&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;element-with-scroll&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Основные различия &lt;code&gt;+&lt;/code&gt; и &lt;code&gt;~&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;+&lt;/code&gt; выбирает &lt;strong&gt;только один&lt;/strong&gt; элемент, который &lt;strong&gt;непосредственно&lt;/strong&gt; следует за первым элементом.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~&lt;/code&gt; выбирает &lt;strong&gt;все элементы&lt;/strong&gt;, которые &lt;strong&gt;следуют&lt;/strong&gt; за первым элементом, но не обязательно сразу за ним.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Посмотрел на разметку ещё раз и понял, что элементы видны всегда, а не по условию, поэтому просто пофиксил стили для &lt;code&gt;.element-with-scroll&lt;/code&gt;  без всяких соседних селекторов, но хоть потренировался.&lt;/p&gt;
&lt;p&gt;#css&lt;/p&gt;</content:encoded></item><item><title>Notion 👋</title><link>https://cherkashin.dev/posts/225/</link><guid isPermaLink="true">https://cherkashin.dev/posts/225/</guid><description>Notion 👋

Только ленивый не написал, что 9 сентября Notion прекращает работу для российских пользователей. Пару дней назад и у меня появилась желтая плашка, которая говорит “на выход”. Говорят, пользователи платных подписок точно потеряют доступ. Посмотрим, будет ли работать Notion через VPN для пользователей на беспл...</description><pubDate>Fri, 06 Sep 2024 10:03:55 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Notion 👋&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Только ленивый не написал, что 9 сентября Notion прекращает работу для российских пользователей. Пару дней назад и у меня появилась желтая плашка, которая говорит “на выход”. Говорят, пользователи платных подписок точно потеряют доступ. Посмотрим, будет ли работать Notion через VPN для пользователей на бесплатном тарифе или нет.&lt;/p&gt;
&lt;p&gt;У меня пока план миграции такой:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Экспортировал все данные из Notion&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Импортировал в российские аналоги - &lt;a href=&quot;https://yonote.ru/&quot;&gt;Yonote&lt;/a&gt; и &lt;a href=&quot;https://teamly.ru/&quot;&gt;Teamly,&lt;/a&gt; на случай если понадобятся старые заметки в удобно читаемом формате (ну не совсем он удобный)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Обмазываюсь плагинами в Obsidian и пытаюсь разобраться, что лучше “папки или связи”&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Теперь кратко про Obsidian:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Настроил &lt;a href=&quot;https://github.com/Vinzent03/obsidian-git&quot;&gt;интеграцию с гитом,&lt;/a&gt; чтобы бэкапить всё на гитхаб&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Шаблоны Notion заменил на плагин &lt;a href=&quot;https://github.com/SilentVoid13/Templater&quot;&gt;Templates&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Настроил некоторые горячие клавиши, как в VS Code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Вместо баз данных Notion, установил плагин &lt;a href=&quot;https://github.com/marcusolsson/obsidian-projects&quot;&gt;Projects.&lt;/a&gt; Он позволяет отображать данные в виде таблицы или канбан доски, как это было в Notion.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Аналога инлайн баз данных в Obsidian нет, но есть &lt;a href=&quot;https://blacksmithgu.github.io/obsidian-dataview/&quot;&gt;dataview.&lt;/a&gt; С помощью SQL подобного языка запросов Dataview Query Language, можно писать запросы ко всем заметкам в базе знаний.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Для миграции заметок из Notion можно использовать плагин &lt;a href=&quot;https://github.com/obsidianmd/obsidian-importer&quot;&gt;Obsidian Importer.&lt;/a&gt; Я пока импортировал только, базу с постами для телеграмм. Импортировалось отлично. Нужно делать экспорт в HTML формате, не в Markdown. После импорта, настроил отображение с помощью плагина Projects и получилось примерно как было в &lt;a href=&quot;https://github.com/marcusolsson/obsidian-projects&quot;&gt;Notion.&lt;/a&gt; И ощущение, что после этого Obsidian стал иногда подвисать, посмотрим как будет работать дальше.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Создал папку для &lt;a href=&quot;https://youtu.be/PiS3pRRj994?t=679&quot;&gt;zero-links&lt;/a&gt; - по сути теги в виде страниц имена, которых начинаются с двух нулей, для оптимизации поиска.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Так как инлайн баз данных нет, для ведения задач собираюсь попробовать плагин Obsidian Tasks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если вам интересна тема Notion и как с него съехать, то вам &lt;a href=&quot;https://t.me/marianotion&quot;&gt;на канал Марии.&lt;/a&gt; Она активно освещает текущую ситуацию, и альтернативные продукты.&lt;/p&gt;
&lt;p&gt;P.S. Расскажите, как вы ведёте базу знаний или список задач. На что мигрируете, если пользовались Notion? Тупит ли Obsidian у вас? 😅&lt;/p&gt;
&lt;p&gt;#notion #obsidian&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-225-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-225-1.jpg"/></item><item><title>У нас на проекте есть 2 основных правила для написания стилей:</title><link>https://cherkashin.dev/posts/224/</link><guid isPermaLink="true">https://cherkashin.dev/posts/224/</guid><description>У нас на проекте есть 2 основных правила для написания стилей:

У всех CSS-классов должен быть префикс dp-, выбранный по названию продуктаМы используем БЭМ — &lt;block&gt;&lt;element&gt;--&lt;modifier&gt;

Однако есть большой пласт легаси стилей, где эти правила не используются.

И вот, при добавлении monaco-editor’а (текстовый редактор...</description><pubDate>Fri, 23 Aug 2024 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;У нас на проекте есть 2 основных правила для написания стилей:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;У всех CSS-классов должен быть префикс &lt;code&gt;dp-&lt;/code&gt;, выбранный по названию продукта&lt;/li&gt;
&lt;li&gt;Мы используем БЭМ — &lt;code&gt;&amp;#x3C;block&gt;__&amp;#x3C;element&gt;--&amp;#x3C;modifier&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Однако есть большой пласт легаси стилей, где эти правила не используются.&lt;/p&gt;
&lt;p&gt;И вот, при добавлении monaco-editor’а (текстовый редактор на котором построен VS Code) в новую фичу, прилетело ишью — у горизонтального и вертикального скролл-баров разная толщина.&lt;/p&gt;
&lt;p&gt;А вся проблема в том, что наши глобальные стили для класса &lt;code&gt;slider&lt;/code&gt; применяются к элементу с таким же классом в monaco-editor.&lt;/p&gt;
&lt;p&gt;Именно эту проблему и решают префиксы — позволяют избежать коллизии имён с библиотечными классами.&lt;/p&gt;
&lt;p&gt;#css #bem&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-224-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-224-1.jpg"/></item><item><title>size-limit</title><link>https://cherkashin.dev/posts/223/</link><guid isPermaLink="true">https://cherkashin.dev/posts/223/</guid><description>size-limit

Вот здесь я писал про source-map-explorer и о том, как с его помощью анализировать размер бандла. Но, чтобы не приходилось анализировать бандл, лучше предотвратить его раздувание.

Это можно сделать на этапе CI с помощью size-limit.

Как использовать❓

Устанавливаем size-limit и плагин @size-limit/file, нео...</description><pubDate>Mon, 19 Aug 2024 10:00:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/ai/size-limit&quot;&gt;size-limit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev/220&quot;&gt;Вот здесь&lt;/a&gt; я писал про &lt;a href=&quot;https://create-react-app.dev/docs/analyzing-the-bundle-size/&quot;&gt;source-map-explorer&lt;/a&gt; и о том, как с его помощью анализировать размер бандла. Но, чтобы не приходилось анализировать бандл, лучше предотвратить его раздувание.&lt;/p&gt;
&lt;p&gt;Это можно сделать на этапе CI с помощью &lt;a href=&quot;https://github.com/ai/size-limit&quot;&gt;size-limit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Как использовать❓&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Устанавливаем &lt;code&gt;size-limit&lt;/code&gt; и плагин &lt;code&gt;@size-limit/file&lt;/code&gt;, необходимый для анализа web-приложений.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;shell&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; --save-dev&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; size-limit&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; @size-limit/file&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Добавляем когфиг size-limit в &lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;  &quot;size-limit&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;      &quot;limit&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;35 kB&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;      &quot;path&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;dist/app-*.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;      &quot;gzip&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Добавляем запуск size-limit в скрипт, который вы запускаете на CI&lt;/li&gt;
&lt;/ol&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;  &quot;scripts&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;    &quot;size&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;npm run build &amp;#x26;&amp;#x26; size-limit&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;    &quot;test&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;vitest &amp;#x26;&amp;#x26; eslint . &amp;#x26;&amp;#x26; npm run size&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Если вы пользуетесь гитхабом, то можете использовать &lt;a href=&quot;https://github.com/andresz1/size-limit-action&quot;&gt;GitHub action&lt;/a&gt;, который добавляет в качестве комментария изменение размера бандла.&lt;/p&gt;
&lt;p&gt;Также size-limit поддерживает задание &lt;a href=&quot;https://github.com/ai/size-limit/?tab=readme-ov-file#js-application-and-time-based-limit&quot;&gt;временных лимитов&lt;/a&gt; на исполнение вашего кода и использует для этого “безголовый хром”.&lt;/p&gt;
&lt;p&gt;#frontend #performance #tools #ci&lt;/p&gt;</content:encoded></item><item><title>Первый шок от последних событий начал проходить, поэтому вчера я немного разобрал инбокс и нашёл в…</title><link>https://cherkashin.dev/posts/222/</link><guid isPermaLink="true">https://cherkashin.dev/posts/222/</guid><description>Первый шок от последних событий начал проходить, поэтому вчера я немного разобрал инбокс и нашёл в нём статью, которой решил с вами поделиться “4 тысячи заметок?! Как я веду личную базу знаний в Obsidian”.

Автор рассказывает, как ему надоело забывать важную информацию и он решил завести личную базу знаний в Obsidian, ...</description><pubDate>Fri, 16 Aug 2024 09:05:05 GMT</pubDate><content:encoded>&lt;p&gt;Первый шок от последних событий начал проходить, поэтому вчера я немного разобрал инбокс и нашёл в нём статью, которой решил с вами поделиться “&lt;a href=&quot;https://habr.com/ru/articles/833550/&quot;&gt;4 тысячи заметок?! Как я веду личную базу знаний в Obsidian&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;Автор рассказывает, как ему надоело забывать важную информацию и он решил завести личную базу знаний в Obsidian, вдохновившись Zettelkasten.&lt;/p&gt;
&lt;p&gt;Zettelkasten – это такая система ведения личных заметок, в которой каждая заметка:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Атомарна. То есть независима и содержит одну мысль.&lt;/li&gt;
&lt;li&gt;Имеет контекст. Например, размечена по тегам, темам.&lt;/li&gt;
&lt;li&gt;Связана с другими знаниями в системе.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt; — это приложение для заметок на максималках. Главное преимущество перед тем же Notion — очень просто добавить новую связь между заметками и легко масштабировать базу (ну и данные все хранятся локально, насколько я помню). Автор использовал видео &lt;a href=&quot;https://youtu.be/PiS3pRRj994?si=m6-xBiafSosnQmBP&quot;&gt;Виктора Теплова&lt;/a&gt; для настройки Obsidian.&lt;/p&gt;
&lt;p&gt;Используя подобную систему, достаточно просто &lt;strong&gt;писать статьи/тексты&lt;/strong&gt;, ведь у тебя нет проблемы чистого листа. Ты можешь найти уже сохранённую информацию по одному из тегов, и остаётся лишь сформировать линию повествования.&lt;/p&gt;
&lt;p&gt;Также автор описывает, что ведёт &lt;a href=&quot;https://habr.com/ru/articles/833550/#:~:text=%D0%BF%D0%B8%D1%81%D1%8C%D0%BC%D0%B0%2C%20%D0%BF%D1%80%D0%B5%D0%B7%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D0%B8%D0%B9%2C%20%D1%80%D0%B5%D1%87%D0%B8.-,%D0%94%D0%BD%D0%B5%D0%B2%D0%BD%D0%B8%D0%BA,-%D0%9B%D0%B8%D1%87%D0%BD%D1%8B%D0%B9%20%D0%B4%D0%BD%D0%B5%D0%B2%D0%BD%D0%B8%D0%BA%20%D1%82%D0%BE%D0%B6%D0%B5&quot;&gt;дневник&lt;/a&gt; в своей базе знаний, это помогает поразмышлять о том, что действительно важно. В жизни человека не происходит то, о чем он не мыслит, поэтому такое ретро очень помогает двигаться в нужном направлении.&lt;/p&gt;
&lt;p&gt;Вчера я тоже решил записать, чего полезного я сделал за прошедший день и понял, что кроме работы там ничего нет. Поэтому я соглашусь с автором, порой стоит остановиться и подумать, “туда ли я иду”.&lt;/p&gt;
&lt;p&gt;В общем, рекомендую &lt;a href=&quot;https://habr.com/ru/articles/833550/&quot;&gt;прочитать статью целиком&lt;/a&gt;, тем более, что она совсем небольшая.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;А расскажите,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;чем пользуетесь вы для ведения заметок?&lt;/li&gt;
&lt;li&gt;какие подходы и практики используете?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я &lt;a href=&quot;https://habr.com/ru/articles/696698/&quot;&gt;пользуюсь Notion&lt;/a&gt;. Но вот на днях пришло письмо от Miro, о том, что они “не могут обслуживать клиентов, зарегистрированных в запрещённом регионе” с 12 сентября. И кто сказал, что скоро Notion не пришлёт такое же письмо, возможно стоит начинать искать альтернативы …&lt;/p&gt;
&lt;p&gt;#obsidian #fridayreading&lt;/p&gt;</content:encoded></item><item><title>Со стороны может показаться, что у нас, у программистов, очень лёгкая работа. Как любит говорить…</title><link>https://cherkashin.dev/posts/221/</link><guid isPermaLink="true">https://cherkashin.dev/posts/221/</guid><description>Со стороны может показаться, что у нас, у программистов, очень лёгкая работа. Как любит говорить мой тренер по теннису: “мол успешные айтишники сидят где-нибудь в эмиратах, птягивают кофе в кафешках и в ус не дуют”. В чем-то он может и прав, но почему-то не у всех получается “войти в айти”. А те, кто вошел, только и го...</description><pubDate>Sat, 10 Aug 2024 09:09:54 GMT</pubDate><content:encoded>&lt;p&gt;Со стороны может показаться, что у нас, у программистов, очень лёгкая работа. Как любит говорить мой тренер по теннису: “мол успешные айтишники сидят где-нибудь в эмиратах, птягивают кофе в кафешках и в ус не дуют”. В чем-то он может и прав, но почему-то не у всех получается “войти в айти”. А те, кто вошел, только и говорят о выгорании.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/articles/598517/&quot;&gt;Года 3 назад я писал, что я делаю&lt;/a&gt;, чтобы не перегореть. С тех пор добавилось ещё несколько привычек.&lt;/p&gt;
&lt;p&gt;🎾 Я начал играть в &lt;strong&gt;большой теннис&lt;/strong&gt;. Пока бегаешь по корту и чуть ли не выплёвываешь свои лёгкие, совсем забываешь о работе.&lt;/p&gt;
&lt;p&gt;🏃‍♂️ С нового года я начал делать зарядку, увидел пост у &lt;a href=&quot;https://t.me/frontengineer/85&quot;&gt;Евгения Шушкова&lt;/a&gt; и тоже решил попробовать. Не уверен, что я чувствую себя намного лучше, но зарядка определённо помогает проснуться. Но что гораздо лучше, она помогает на какие-то 15 минут немного избавиться от тревожности.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Обычно я делаю &lt;a href=&quot;https://www.youtube.com/watch?v=viI3VEiVsQA&amp;#x26;list=PL0KWAvKzASSdieLaU-UH12tgHHnuYJzOn&amp;#x26;index=2&quot;&gt;вот этот комплекс на 15 минут&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Или этот &lt;a href=&quot;https://www.youtube.com/watch?v=Ie1fzUxydTY&amp;#x26;list=PL0KWAvKzASSdieLaU-UH12tgHHnuYJzOn&amp;#x26;index=23&quot;&gt;на 5 минут, когда лень&lt;/a&gt;, но чтобы не потерять привычку&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;💪 В дополнение к зарядке стараюсь пару раз в неделю подтягиваться или отжиматься. Или же делаю &lt;a href=&quot;https://www.youtube.com/watch?v=VSzEycJUBaY&amp;#x26;t=265s&quot;&gt;вот этот комплекс на пресс&lt;/a&gt;, первые 4 минуты, потом пресс умирает.&lt;/p&gt;
&lt;p&gt;📱В мае &lt;a href=&quot;https://t.me/cherkashindev/206&quot;&gt;я отписался от новостных каналов&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;К сожалению, очередная попытка перестать читать новости на этой неделе провалилась. Сложно не следить за ними, когда ты живешь в Курске. В теннис тоже не поиграешь из-за постоянной сирены за окном. Поэтому именно сейчас я в полной мере почувствовал пользу зарядки.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В такие моменты важно иметь чувство контроля над ситуацией. И оно хоть немного появляется, когда получается помочь тем, кому сейчас тяжело.&lt;/p&gt;
&lt;p&gt;Если у вас есть желание помочь людям, кто вынуждено покинул свои дома из-за всей ситуации в Курской области, это можно сделать &lt;a href=&quot;https://vk.com/pomotsch_kursk&quot;&gt;здесь&lt;/a&gt;. Или напишите &lt;a href=&quot;https://t.me/cherkalexander&quot;&gt;мне в личку&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Я вообще считаю, программирование это не про “писать код”, это про людей. И мы можем сделать жизнь людей лучше не только написав очередные 1000 строчек кода.&lt;/p&gt;</content:encoded></item><item><title>source-map-explorer</title><link>https://cherkashin.dev/posts/220/</link><guid isPermaLink="true">https://cherkashin.dev/posts/220/</guid><description>source-map-explorer

На прошлой неделе анализировал размер главного бандла мобильной версии нашего приложения.

В спешке мы накосячили с импортами и бандл раздулся.

🤔 Как анализировать?

Для анализа использовал утилиту source-map-explorer.

При запуске, утилита генирирует древовидную карту, с помощью которой можно ув...</description><pubDate>Tue, 06 Aug 2024 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;source-map-explorer&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На прошлой неделе анализировал размер главного бандла мобильной версии нашего приложения.&lt;/p&gt;
&lt;p&gt;В спешке мы накосячили с импортами и бандл раздулся.&lt;/p&gt;
&lt;p&gt;🤔 &lt;strong&gt;Как анализировать?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Для анализа использовал утилиту &lt;a href=&quot;https://create-react-app.dev/docs/analyzing-the-bundle-size/&quot;&gt;source-map-explorer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;При запуске, утилита генирирует древовидную карту, с помощью которой можно увидеть, какие именно файлы попадают в бандл.&lt;/p&gt;
&lt;p&gt;К сожалению, почему именно это что-то попало в бандл утилита не говорит.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;В чём была проблема?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Иногда мы ленимся и в файле компонента кладём какую-нибудь утилитную функцию, enum или константу, а потом где-то в другом месте импортируем их.&lt;/p&gt;
&lt;p&gt;Так вот, когда мы их импортируем, то в бандл “засасывает” не только импортируемую функцию, но и весь компонент, из-за чего размер бандла и увеличивается.&lt;/p&gt;
&lt;p&gt;P.S. А какими инструментами пользуетесь вы?&lt;/p&gt;
&lt;p&gt;#frontend #performance #tools&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-220-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-220-1.jpg"/></item><item><title>Как инспектировать разметку попапов</title><link>https://cherkashin.dev/posts/219/</link><guid isPermaLink="true">https://cherkashin.dev/posts/219/</guid><description>Как инспектировать разметку попапов

Если у вас возникают проблемы с дебагом попапов, которые открываются только по ховеру, то вот несколько простых советов:

Способ 1: Открываете DevTools ⇒ Вкладка Sources ⇒ Далее наводите мышкой на свой элемент ⇒ Нажимаете F8, чтобы приостановить выполнение скрипта

Способ 2: Открыва...</description><pubDate>Tue, 30 Jul 2024 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Как инспектировать разметку попапов&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Если у вас возникают проблемы с дебагом попапов, которые открываются только по ховеру, то вот несколько простых советов:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Способ 1&lt;/strong&gt;: Открываете DevTools ⇒ Вкладка Sources ⇒ Далее наводите мышкой на свой элемент ⇒ Нажимаете F8, чтобы приостановить выполнение скрипта&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Способ 2:&lt;/strong&gt; Открываете DevTools ⇒ Находите тег body или тот тег, внутри которого появляется попап и нажимаете на нём правой кнопкой ⇒ Выбираете “Break on ⇒ subtree modification” и дебажите до тех пор пока не появится попап.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Способ 3:&lt;/strong&gt; Мой любимый. Вставляете скрипт в консоль и у вас есть 3 секунды чтобы показать попап. Именно этим способом пользовался пока не узнал про первый 😄&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;setTimeout&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;debugger&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3000&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;#frontend #devtools&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-219-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-219-1.jpg"/></item><item><title>Если бы вас спросили, что самое сложное в вашей работе, чтобы вы ответили?</title><link>https://cherkashin.dev/posts/218/</link><guid isPermaLink="true">https://cherkashin.dev/posts/218/</guid><description>Если бы вас спросили, что самое сложное в вашей работе, чтобы вы ответили?
Я думаю одна из самых сложных вещей - читать чужой код, или свой собственный, написанный пару лет назад.

👉 Сегодня статья о том, Как избежать когнитивной перегрузки: способы оптимизации кода для разработчиков.

Вот основные моменты из статьи, ...</description><pubDate>Fri, 26 Jul 2024 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;Если бы вас спросили, что самое сложное в вашей работе, чтобы вы ответили?
Я думаю одна из самых сложных вещей - читать чужой код, или свой собственный, написанный пару лет назад.&lt;/p&gt;
&lt;p&gt;👉 Сегодня статья о том, &lt;a href=&quot;https://habr.com/ru/companies/ncloudtech/articles/818643/&quot;&gt;Как избежать когнитивной перегрузки: способы оптимизации кода для разработчиков&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Вот основные моменты из статьи, если вам лень читать всю статью в пятницу да ещё и летом 😅&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Когнитивная нагрузка – это объем умственной работы, необходимый разработчику для выполнения задачи. Нашим приоритетом должно быть максимальное снижение такой нагрузки в проектах.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Типы когнитивной нагрузки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Внутренняя — изначальная сложность задачи, её нельзя уменьшить.&lt;/li&gt;
&lt;li&gt;Внешняя — создается способом представления информации. То есть то, как написан код, решающий задачу.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Знакомая и простая вещь — не одно и то же&lt;/strong&gt;. Они ощущаются одинаково — та же легкость перемещения по пространству без особых умственных усилий, но по совершенно разным причинам. Каждый «умный» и нестандартный прием приведет к трате времени на обучение для остальных разработчиков. После того, как они его освоят, им будет легче работать с кодом. Именно поэтому не так легко понять, как можно упростить уже знакомый код.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Нет никакой «упрощающей силы», влияющей на базу кода, кроме вашего сознательного выбора. Упрощение требует усилий, а люди часто спешат.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Отладка в два раза сложнее написания кода. Следовательно, если вы пишете код максимально хитроумно, вы по определению недостаточно умны, чтобы его отладить.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Лучшие компоненты — это те, которые обеспечивают мощную функциональность при простом интерфейсе.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Лучше большой модуль с простым API, чем много маленьких модулей с раздутым API, которые связаны между собой.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Хорошо продуманный монолит с действительно изолированными модулями часто намного удобнее и гибче, чем набор микросервисов.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DRY (Don’t repeat yourself) — хотя в целом это хорошее и фундаментальное правило, его чрезмерное использование приводит к непосильной когнитивной нагрузке. У DRY есть альтернатива &lt;strong&gt;—&lt;/strong&gt;  &lt;a href=&quot;https://kentcdodds.com/blog/aha-programming&quot;&gt;AHA Programming&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Вы можете слишком рано извлечь общую функциональность, основываясь на предполагаемом сходстве, которого на самом деле в долгосрочной перспективе может не быть. Это может привести к ненужным абстракциям, которые будет непросто модифицировать или расширять.&lt;/li&gt;
&lt;li&gt;«Небольшое копирование лучше, чем небольшая зависимость».&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/companies/ncloudtech/articles/818643/&quot;&gt;https://habr.com/ru/companies/ncloudtech/articles/818643/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #essential&lt;/p&gt;</content:encoded></item><item><title>Как я обычно узнаю о новых фичах в C# ❓</title><link>https://cherkashin.dev/posts/217/</link><guid isPermaLink="true">https://cherkashin.dev/posts/217/</guid><description>Как я обычно узнаю о новых фичах в C# ❓

О новых фичах в C# я обычно узнаю с помощью подсказок Райдера — IDE для C# от JetBrains.

В общем, обновился, пишу код, и Райдер предлагает что-то исправить там, где раньше все было окей. Думаю — ну ок, давай исправим. Но ощущение, что он перепутал C# c JavaScript.

string[] arr...</description><pubDate>Wed, 17 Jul 2024 10:03:24 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Как я обычно узнаю о новых фичах в C# ❓&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;О новых фичах в C# я обычно узнаю с помощью подсказок Райдера — IDE для C# от JetBrains.&lt;/p&gt;
&lt;p&gt;В общем, обновился, пишу код, и Райдер предлагает что-то исправить там, где раньше все было окей. Думаю — ну ок, давай исправим. Но ощущение, что он перепутал C# c JavaScript.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;string[] array = new [] { “a”, “b”, }&lt;/code&gt; предлагает заменить на &lt;code&gt;string[] array = [&quot;a&quot;, &quot;b&quot;]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Array.Empty&amp;#x3C;string&gt;()&lt;/code&gt; на &lt;code&gt;[]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;List&amp;#x3C;string&gt; list = new (vowels)&lt;/code&gt; на &lt;code&gt;List&amp;#x3C;string&gt; list = [.. vowels]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Особенно интересен последний пример, очень уж напоминающий spread оператор из JS. И действительно, в C# его тоже завезли, правда по пути потеряли одну точку и назвали spread element.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;csharp&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[] &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;row0&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[] &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;row1&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[] &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;row2&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[] &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;example1&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;row0, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;row1, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;row2];&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;example2&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;row0, row1[&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;В общем, в C# 12 поднасыпали синтаксического сахара для работы с коллекциями. А ещё прихватили &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/primary-constructors&quot;&gt;Primary конструктор из Scala&lt;/a&gt;. Это когда конструктор объявляется сразу после имени класса.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;csharp&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; BankAccount&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; accountID&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; owner&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; AccountID&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;; } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; accountID;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Owner&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;; } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; owner;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; ToString&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; $&quot;Account ID: {&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;AccountID&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}, Owner: {&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;Owner&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#inline-arrays&quot;&gt;Подробнее о релизе C# 12 здесь.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;А о том, как добавить поддержку спред оператора для кастомных коллекций &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions#collection-builder&quot;&gt;описывается тут&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#csharp&lt;/p&gt;</content:encoded></item><item><title>function(): Promise 🆚 async function(): Promise</title><link>https://cherkashin.dev/posts/216/</link><guid isPermaLink="true">https://cherkashin.dev/posts/216/</guid><description>function(): Promise 🆚 async function(): Promise

Существует небольшая, но довольно важная разница между функцией, которая просто возвращает промис, и функцией, которая была объявлена с помощью ключевого слова async.

Пример

function fn(obj) {
  const someProp = obj.someProp
  return Promise.resolve(someProp)
}

async...</description><pubDate>Mon, 08 Jul 2024 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;code&gt;function(): Promise&lt;/code&gt; 🆚 &lt;code&gt;async function(): Promise&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Существует небольшая, но довольно важная разница между функцией, которая просто возвращает промис, и функцией, которая была объявлена с помощью ключевого слова &lt;code&gt;async&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Пример&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; fn&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;obj&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; someProp&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; obj.someProp&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(someProp)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; asyncFn&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;obj&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; someProp&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; obj.someProp&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(someProp)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;asyncFn&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;Catched&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// =&gt; &apos;Catched&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;Catched&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// =&gt; TypeError: Cannot read property &apos;someProp&apos; of undefined&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;при объявлении функции с ключевым словом &lt;code&gt;async&lt;/code&gt; JavaScript гарантирует, что функция вернёт &lt;code&gt;Promise&lt;/code&gt;, даже если в ней произошла ошибка&lt;/li&gt;
&lt;li&gt;если функция возвращает &lt;code&gt;Promise&lt;/code&gt;, но объявлена без &lt;code&gt;async&lt;/code&gt; то &lt;code&gt;catch&lt;/code&gt; не поймает ошибку, если в функции произошла ошибка&lt;/li&gt;
&lt;li&gt;дело в том, что ошибки произошедшие внутри конструктора &lt;code&gt;new Promise((resolve, reject) =&gt; { throw new ... })&lt;/code&gt; промиса ловятся. Когда мы добавляем &lt;code&gt;async&lt;/code&gt;, то по сути заворачиваем тело функции в &lt;code&gt;new Promise((resolve, reject) ⇒ {  })&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;То есть, чтобы сделать функции из примера идентичными, нужно завернуть первую функцию в промис.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; fn&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;obj&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;reject&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; someProp&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; obj.someProp;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(someProp);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/articles/475260/&quot;&gt;https://habr.com/ru/articles/475260/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#javascript #frontend&lt;/p&gt;</content:encoded></item><item><title>Сегодня принёс вам одну из лучших статей по код ревью.</title><link>https://cherkashin.dev/posts/215/</link><guid isPermaLink="true">https://cherkashin.dev/posts/215/</guid><description>Сегодня принёс вам одну из лучших статей по код ревью.

В конце статьи автор упоминает фразу, которая уже давно вертелась у меня на языке, и вот здесь она отлично сформулирована.

💡 “Как это ни парадоксально, наличие постоянно полезных и ценных ревью — это признак того, что вы можете добиться большего на других этапах...</description><pubDate>Fri, 05 Jul 2024 10:00:05 GMT</pubDate><content:encoded>&lt;p&gt;Сегодня принёс вам одну из лучших статей по код ревью.&lt;/p&gt;
&lt;p&gt;В конце статьи автор упоминает фразу, которая уже давно вертелась у меня на языке, и вот здесь она отлично сформулирована.&lt;/p&gt;
&lt;p&gt;💡 &lt;strong&gt;“Как это ни парадоксально, наличие постоянно полезных и ценных ревью — это признак того, что вы можете добиться большего на других этапах процесса.”&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Исправлять архитектурные проблемы на фазе код ревью — слишком дорого&lt;/li&gt;
&lt;li&gt;Люди не должны вручную искать проблемы, которые можно найти автоматически&lt;/li&gt;
&lt;li&gt;Одна из целей код ревью — постоянно сужать его рамки, позволяя разработчикам постоянно обнаруживать, что может быть улучшено в других частях процесса разработки
&lt;ul&gt;
&lt;li&gt;Документация&lt;/li&gt;
&lt;li&gt;Онбординг&lt;/li&gt;
&lt;li&gt;Линтеры&lt;/li&gt;
&lt;li&gt;Статические анализаторы&lt;/li&gt;
&lt;li&gt;и т.д.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Также ещё одна мысль, которую доносит автор — &lt;strong&gt;“код ревью не должно быть одинаковым для всех изменений”&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;🐌 Проблемы медленных ревью&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Они медленные 🤷‍♂️  — замедляют релиз на несколько часов или дней&lt;/li&gt;
&lt;li&gt;Поверхностные — не улучшают качество кода, не происходит обмен знаниями.&lt;/li&gt;
&lt;li&gt;Если ревью происходит медленно — разработчики начинают создавать большие пул реквесты, что увеличивает нагрузку на ревьюера и делает код ревью ещё медленнее.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Подходы, которые описываются в статье&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Автор долго придерживался принципа &lt;a href=&quot;https://refactoring.fm/i/145753428/automate-defer-pair&quot;&gt;Ship / Show / Ask&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;🚢 Ship.&lt;/strong&gt; Изменения простые, нет знаний, которыми стоит поделиться — льём в прод без ревью.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;🔍 Show.&lt;/strong&gt; Если изменения простые, но в них есть что-то полезное и ими стоит поделиться (например вы написали новую функцию или компонент), то — сливайте изменения, а потом просите о код ревью. Код ревью — не блокирующий. Я обычно называю это &lt;strong&gt;постревью&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;❓Ask.&lt;/strong&gt; Если вы вносите сложные изменения — дождитесь код ревью и только потом сливайте изменения. Тут код ревью блокирующий.&lt;/p&gt;
&lt;p&gt;Со временем он его немного перефразировал в &lt;a href=&quot;https://refactoring.fm/p/thoughts-on-code-reviews?utm_source=post-email-title&amp;#x26;publication_id=64099&amp;#x26;post_id=145753428&amp;#x26;utm_campaign=email-post-title&amp;#x26;isFreemail=false&amp;#x26;r=omxaq&amp;#x26;triedRedirect=true&amp;#x26;utm_medium=email#:~:text=just%20called%20it-,Automate,-/%20Defer%20/%20Pair%3A&quot;&gt;Automate / Defer / Pair&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;🤖 Automate.&lt;/strong&gt; Если в изменениях нет знаний, которыми стоило бы поделиться, а в коде особо нечего улучшить — пропускаем ревью и полагаемся на линтеры, статические анализаторы и тесты.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;↪️ Defer (отложить).&lt;/strong&gt;  В зрелом и проверенном процессе разработки большинство изменений нужно ревьюить, но ревью не должно быть блокирующим. Это особенно хорошо работает, когда новая фича деплоится за фича флагом и можно спокойно получить фидбек после деплоя.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;👯 Pair.&lt;/strong&gt; Если корректность изменений очень важна: их сложно откатить или изменения связаны с оплатой, или же изменения достаточно сложные — то вам нужно работать в &lt;strong&gt;паре&lt;/strong&gt; с ревьюером, созвониться и объяснить ему изменения, чтобы он был в контексте и смог сделать ревью быстрее и качественнее.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#codereview #fridayreading #weekphrase&lt;/p&gt;</content:encoded></item><item><title>Generic React-компоненты</title><link>https://cherkashin.dev/posts/214/</link><guid isPermaLink="true">https://cherkashin.dev/posts/214/</guid><description>Generic React-компоненты

Помню года так 4 назад я писал базовый компонент поиска — стандартное текстовое поле, а когда начинаешь печатать, появляется список найденных элементов.

И тогда я впервые задумался, поддерживает ли React дженерики в связке с TypeScript (а почему бы ему их не поддерживать?).

Каркас компонента...</description><pubDate>Mon, 01 Jul 2024 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Generic React-компоненты&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Помню года так 4 назад я писал базовый компонент поиска — стандартное текстовое поле, а когда начинаешь печатать, появляется список найденных элементов.&lt;/p&gt;
&lt;p&gt;И тогда я впервые задумался, поддерживает ли React дженерики в связке с TypeScript (а почему бы ему их не поддерживать?).&lt;/p&gt;
&lt;p&gt;Каркас компонента выглядит так&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; SearchBoxProps&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;  search&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[] &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[]&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;  renderItem&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; React&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;ReactNode&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  // ...&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; SearchBox&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;props&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; SearchBoxProps&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  // ...&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;А использование так&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;SearchBox&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  search&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  renderItem&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;TypeScript отлично выводит типы, но недавно я узнал, что их можно указать и в JSX. Раньше думал, что будут проблемы из-за угловых скобок &lt;code&gt;&amp;#x3C;&lt;/code&gt;  &lt;code&gt;&gt;&lt;/code&gt; в дженериках&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;SearchBox&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  search&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{() =&gt; [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  renderItem={(item) =&gt; &amp;#x3C;div&gt;{item}&amp;#x3C;/div&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;💡 Когда использовать дженерики для реакт-компонентов?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда компонент может принимать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;данные разных типов&lt;/li&gt;
&lt;li&gt;и рендер-пропсы/слоты, чтобы преобразовать эти данные в UI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ещё один пример можете посмотреть вот &lt;a href=&quot;https://www.youtube.com/watch?v=zqz-lEHjJr4&amp;#x26;ab_channel=MattPocock&quot;&gt;в этом видео&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#react #frontend #typescript&lt;/p&gt;</content:encoded></item><item><title>Мемоизация селекторов в Zustand</title><link>https://cherkashin.dev/posts/213/</link><guid isPermaLink="true">https://cherkashin.dev/posts/213/</guid><description>Мемоизация селекторов в Zustand

Если вы используете Zustand, то знаете, что computed значения реализуются с помощью селекторов.

const userPrs = useChartsStore((state) =&gt; {
    return state.pullRequests.filter(pr =&gt; pr.author.id === state.user.id);
});

В примере выше:

при каждом обновлении стейта значение селектора ...</description><pubDate>Mon, 17 Jun 2024 10:00:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Мемоизация селекторов в Zustand&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Если вы используете Zustand, то знаете, что computed значения реализуются с помощью селекторов.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; userPrs&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useChartsStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.pullRequests.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;pr&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; pr.author.id &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.user.id);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;В примере выше:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;при каждом обновлении стейта значение селектора будет вычисляться заново&lt;/li&gt;
&lt;li&gt;это приведёт к ре-рендеру компонента, так как каждый раз мы постоянно возвращает новый массив по ссылке, а &lt;a href=&quot;https://github.com/pmndrs/zustand?tab=readme-ov-file#selecting-multiple-state-slices&quot;&gt;по-умолчанию используется строгое сравнение&lt;/a&gt; (old === new).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Чтобы решить эту проблему в Zustand есть хук &lt;code&gt;useShallow&lt;/code&gt; , который сделает “поверхностное” сравнение предыдущего и нового значения. Если они равны — ре-рендер не произойдёт.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; userPrs&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useChartsStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;useShallow&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.pullRequests.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;pr&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; pr.author.id &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.user.id);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Но при этом селектор всё равно выполнится, и в большинстве случаев нам не нужно об этом заботиться. Проблема появляется если выполнение селектора занимает много времени или же он вызывается много раз в различных компонентах или других селекторах.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pmndrs/zustand/discussions/387#discussioncomment-731593&quot;&gt;Автор Zustand упоминает&lt;/a&gt;, что можно нарушить согласованность данных и просто положить вычисляемые данные в стейт (но в этом случае нужно вручную следить за их актуальностью).&lt;/p&gt;
&lt;p&gt;Также он отмечает, что для этих целей можно использовать метод &lt;code&gt;memoize&lt;/code&gt; из его библиотеки &lt;a href=&quot;https://github.com/dai-shi/proxy-memoize&quot;&gt;proxy-memoize&lt;/a&gt; (для redux есть &lt;a href=&quot;https://github.com/reduxjs/reselect&quot;&gt;reselect&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Аналогично immer’у proxy-memoize работает на основе &lt;code&gt;Proxy&lt;/code&gt;. &lt;code&gt;memoize&lt;/code&gt; запоминает предыдущий параметр функции и свойства к которым обращались в селекторе (для этого и нужен &lt;code&gt;Proxy&lt;/code&gt;). При следующем выполнении функции, он проверит изменились ли используемые свойства, если нет — вернёт значение, вычисленное в прошлый раз.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; authorSelector&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; memoize&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.pullRequests.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;pr&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; pr.author.id &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.user.id));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; userPrs&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useChartsStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(authorSelector);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Конечно, нужно помнить, что мемоизировать можно только “чистую” функцию — если  она возвращает одни и те же значения в ответ на одни и те же аргументы&lt;/p&gt;
&lt;p&gt;Так, обернув пару селекторов в &lt;code&gt;memoize&lt;/code&gt;, я ускорил фильтрацию пул-реквестов в более чем 20 раз (900мс ⇒ 40мс).&lt;/p&gt;
&lt;p&gt;#react #zustand #statemanagement #frontend&lt;/p&gt;</content:encoded></item><item><title>На прошлой неделе проверял почту и наткнулся на рассылку от Я.Практикума “Что нельзя делать…</title><link>https://cherkashin.dev/posts/212/</link><guid isPermaLink="true">https://cherkashin.dev/posts/212/</guid><description>На прошлой неделе проверял почту и наткнулся на рассылку от Я.Практикума “Что нельзя делать хорошему менеджеру”. Одна из упоминаемых проблем – “Срезание углов” или экономия времени на продумывании ТЗ. Чтобы избежать проблемы понимания требований исполнителем – нужно научиться смотреть на ТЗ глазами новичка. Такое же пр...</description><pubDate>Fri, 14 Jun 2024 10:02:12 GMT</pubDate><content:encoded>&lt;p&gt;На прошлой неделе проверял почту и наткнулся на рассылку от Я.Практикума “Что нельзя делать хорошему менеджеру”. Одна из упоминаемых проблем – “Срезание углов” или экономия времени на продумывании ТЗ. Чтобы избежать проблемы понимания требований исполнителем – нужно научиться смотреть на ТЗ глазами новичка. Такое же правило я применяю при написании кода:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Нужно смотреть на код глазами новичка.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Представьте, что вы новый сотрудник и ничего не знаете кроме того, что написано в коде.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Поймёт ли он, что именно происходит в коде?&lt;/li&gt;
&lt;li&gt;Почему это реализовано именно так?&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-212-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-212-1.jpg"/></item><item><title>peerDependencies</title><link>https://cherkashin.dev/posts/211/</link><guid isPermaLink="true">https://cherkashin.dev/posts/211/</guid><description>peerDependencies

Недавно делал код ревью и заметил, что в pnpm-lock.yaml (альтернатива yarn.lock в pnpm) добавлена 17-я версия реакта, хотя на проекте мы используем 18-ю. Нам не нужно тянуть в проект 2 версии реакта — поэтому идём разбираться.

Дело в том, что в библиотеке react-cheetah-grid, которую мы используем для...</description><pubDate>Mon, 10 Jun 2024 10:03:27 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;peerDependencies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Недавно делал код ревью и заметил, что в &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; (альтернатива &lt;code&gt;yarn.lock&lt;/code&gt; в pnpm) добавлена 17-я версия реакта, хотя на проекте мы используем 18-ю. Нам не нужно тянуть в проект 2 версии реакта — поэтому идём разбираться.&lt;/p&gt;
&lt;p&gt;Дело в том, что в библиотеке &lt;code&gt;react-cheetah-grid&lt;/code&gt;, которую мы используем для рендера длинных таблиц, реакт указан в секции &lt;code&gt;dependencies&lt;/code&gt; вместо &lt;code&gt;peerDependencies&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;dependencies vs peerDependencies&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dependencies&lt;/code&gt;: пакеты, которые необходимы для работы вашего приложения и устанавливаются автоматически&lt;/li&gt;
&lt;li&gt;&lt;code&gt;peerDependencies&lt;/code&gt;: пакеты, которые должны быть уже установлены в среде, где используется ваш пакет, чтобы избежать конфликтов версий&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Чтобы быстро исправить проблему — можно переопределить версию реакта для определённого пакета в &lt;code&gt;pnpm&lt;/code&gt;  с помощью метода &lt;a href=&quot;https://pnpm.io/pnpmfile#hooksreadpackagepkg-context-pkg--promisepkg&quot;&gt;readPackage.&lt;/a&gt; Также нужно откатить изменения в &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; и запустить &lt;code&gt;pnpm install&lt;/code&gt; .&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// .pnpmfile.cjs&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;./package.json&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; readPackage&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;pkg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (pkg.name &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;react-cheetah-grid&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    pkg.dependencies[&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;react&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; package.dependencies[&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;react&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    pkg.dependencies[&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;react-dom&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; package.dependencies[&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;react-dom&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; pkg;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  hooks: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    readPackage,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Но затем лучше создать ишью в репозитории библиотеки или отправить &lt;a href=&quot;https://github.com/future-architect/cheetah-grid/pull/420/files&quot;&gt;пул реквест.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#react #pnpm&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-211-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-211-1.jpg"/></item><item><title>На прошлой неделе на Хабре объявили победителей конкурса «Технотекст 2023». Моя статья, к…</title><link>https://cherkashin.dev/posts/210/</link><guid isPermaLink="true">https://cherkashin.dev/posts/210/</guid><description>На прошлой неделе на Хабре объявили победителей конкурса «Технотекст 2023». Моя статья, к сожалению, не стала победителем, так что будем пробовать ещё раз в следующем году (или нет).

Если не знаете, что почитать, то здесь можно найти победителей как текущего сезона, так и прошлых лет.

Я пока прочитал только:

VK: Fig...</description><pubDate>Fri, 07 Jun 2024 09:59:01 GMT</pubDate><content:encoded>&lt;p&gt;На прошлой неделе &lt;a href=&quot;https://habr.com/ru/companies/habr/articles/817837/&quot;&gt;на Хабре объявили победителей конкурса «Технотекст 2023»&lt;/a&gt;. Моя статья, к сожалению, не стала победителем, так что будем пробовать ещё раз в следующем году (или нет).&lt;/p&gt;
&lt;p&gt;Если не знаете, что почитать, то &lt;a href=&quot;https://habr.com/ru/technotext/2023/winners/&quot;&gt;здесь можно найти победителей&lt;/a&gt; как текущего сезона, так и прошлых лет.&lt;/p&gt;
&lt;p&gt;Я пока прочитал только:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/vk/articles/790686/&quot;&gt;VK: Figma to Frontend: как мы автоматически синхронизируем дизайн и код&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И планирую прочитать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/774722/&quot;&gt;Принципы непрерывного рефакторинга&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/yandex/articles/718084/&quot;&gt;Полное понимание асинхронности в браузере&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #habr&lt;/p&gt;</content:encoded></item><item><title>zustand и redux-devtools</title><link>https://cherkashin.dev/posts/208/</link><guid isPermaLink="true">https://cherkashin.dev/posts/208/</guid><description>zustand и redux-devtools

Я всё ещё пытаюсь доделать свой пет-проект для построения графиков на основе данных из пул реквестов и комментариев.

В качестве стейтменеджера использую zustand. Своих девтулзов у него нет, но разработчики реализовали middleware для отображения данных в redux-devtools.

При использовании zust...</description><pubDate>Mon, 03 Jun 2024 10:03:46 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;zustand и redux-devtools&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я всё ещё пытаюсь доделать свой пет-проект для построения графиков на основе данных из пул реквестов и комментариев.&lt;/p&gt;
&lt;p&gt;В качестве стейтменеджера использую &lt;a href=&quot;https://github.com/pmndrs/zustand&quot;&gt;zustand&lt;/a&gt;. Своих девтулзов у него нет, но разработчики реализовали middleware для отображения данных в &lt;a href=&quot;https://github.com/reduxjs/redux-devtools&quot;&gt;redux-devtools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;При использовании zustand’а часто создают много маленьких сторов, поэтому чтобы не оборачивать каждый вызов &lt;code&gt;create&lt;/code&gt; в middleware — пишем небольшой утилитный метод &lt;code&gt;createStore&lt;/code&gt;:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;ts&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { create } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;zustand&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { devtools } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;zustand/middleware&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; createStore&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Parameters&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; devtools&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; create&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;()(&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;devtools&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(fn, { name, enabled: process.env.&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; !==&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;production&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; }));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Через некоторое время заметил, что при обновлении стейта проседает производительность — показ диалога занимает 2 секунды.&lt;/p&gt;
&lt;p&gt;Нашёл 2 проблемы:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Стандартная. Весь контент страницы был в одном компоненте, поэтому при обновлении локального стейта перерендеривались все компоненты.&lt;/p&gt;
&lt;p&gt;✅ Решение простое — вынес все 20+ графиков в отдельный компонент и обернул его в &lt;code&gt;React.memo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Работает быстрее, но всё ещё есть небольшая задержка. Девтулзы реакта ничего не показывают — запускаю стандартные девтулзы хрома. Вижу, что большую часть времени занимает не обновление стейта, а какой-то левый скрипт. Перехожу в его исходники и вижу там слово “Redux”.&lt;/p&gt;
&lt;p&gt;ℹ️ Отключаем redux-devtools и всё работает очень быстро.&lt;/p&gt;
&lt;p&gt;❓Всё дело в том, что у меня в сторе хранятся все пулреквесты (4000) и комментарии (5200) за год, из-за такого количества данных redux-devtools подтормаживает.&lt;/p&gt;
&lt;p&gt;В общем, проблема не всегда в вашем коде, но это в любом случае — это ваша проблема 😄.&lt;/p&gt;
&lt;p&gt;#zustand #react #statemanagement&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-208-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-208-1.jpg"/></item><item><title>Уже давно поймал себя на мысли, что стал редко посещать конференции. Поэтому решил всю эту неделю…</title><link>https://cherkashin.dev/posts/207/</link><guid isPermaLink="true">https://cherkashin.dev/posts/207/</guid><description>Уже давно поймал себя на мысли, что стал редко посещать конференции. Поэтому решил всю эту неделю провести на Podlodka React Crew.

👉 Для тех кто ни разу не был — формат следующий:

С понедельника по пятницу: — один доклад утром в 11:00, один вечером в 19:00Разные форматы: доклады, собесы, круглые столыОтдельное спаси...</description><pubDate>Fri, 31 May 2024 11:53:33 GMT</pubDate><content:encoded>&lt;p&gt;Уже давно поймал себя на мысли, что стал редко посещать конференции. Поэтому решил всю эту неделю провести на &lt;a href=&quot;https://podlodka.io/reactcrew&quot;&gt;Podlodka React Crew.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;👉 Для тех кто ни разу не был — формат следующий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;С понедельника по пятницу: — один доклад утром в 11:00, один вечером в 19:00&lt;/li&gt;
&lt;li&gt;Разные форматы: доклады, собесы, круглые столы&lt;/li&gt;
&lt;li&gt;Отдельное спасибо организаторам за рандом кофе, это когда вы созваниваетесь со случайны человеком и болтаете о чём вашей душе угодно.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Узнал много нового:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В реакте одни проблемы и лучше переходить на другой фреймвор. Правда но на какой, так никто и не рассказал, так что остаёмся&lt;/li&gt;
&lt;li&gt;У Effector’а давние тёрки с Reatom’ом 🔥&lt;/li&gt;
&lt;li&gt;При открытии собственного бара — самое сложное договориться с поставщиками&lt;/li&gt;
&lt;li&gt;Для создания классных интерактивных презентации можно использовать:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://revealjs.com/&quot;&gt;reveal.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shwr.me/&quot;&gt;shower.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sli.dev/&quot;&gt;sli.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gamma.app/&quot;&gt;gamma.app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;У JQuery вышла бета мажорной 4-ой версии 😅&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;💡 Ну а если серьёзно, то было много интересных докладов. Вот некоторые заметки, которые сделал за время конференции:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Архитектура программного обеспечения — совокупность важнейших решений об организации программной системы&lt;/li&gt;
&lt;li&gt;В стартапе при выборе архитектуры — главное принять поменьше плохих решений.&lt;/li&gt;
&lt;li&gt;Если вы что-то не успели отрефакторить — новые разработчики быстро растащат этот код по всему проекту.&lt;/li&gt;
&lt;li&gt;Если вы хотите мигрировать на новую технологию, но это не влияет на показатели бизнеса — возможно эта миграция и не нужна.&lt;/li&gt;
&lt;li&gt;В императивном подходе мы описываем, откуда что поменять. А в реактивном — откуда что взять.&lt;/li&gt;
&lt;li&gt;Function as a child component (FACC) — паттерн схожий с Compound Components.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; — движок для блогов.&lt;/li&gt;
&lt;li&gt;Скоро в &lt;a href=&quot;https://feature-sliced.design/&quot;&gt;Feature-Sliced Design&lt;/a&gt; вот вот появится плагин, для файловой структуры проекта и не только 🔥&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ещё хотел подать заявку на открытый микрофон и рассказать, как мы мигрируем с JQuery на React. Даже накидал 20% доклада, но понял, что подготовиться не успею и вовремя остановился, может в следующий раз 😅.&lt;/p&gt;
&lt;p&gt;А вообще атмосфера очень зашла. Я работаю по большей части удалённо, поэтому было приятно почувствовать себя частью сообщества. Организаторам спасибо ♥️&lt;/p&gt;
&lt;p&gt;#about_me #conference&lt;/p&gt;</content:encoded></item><item><title>Сегодня посоветую одну довольно интересную статью (не зря же она была написана в мой день рождения).</title><link>https://cherkashin.dev/posts/206/</link><guid isPermaLink="true">https://cherkashin.dev/posts/206/</guid><description>Сегодня посоветую одну довольно интересную статью (не зря же она была написана в мой день рождения).

Как обхитрить мозг и заставить его полюбить сложные задачи [Дофаминовый детокс]

⛔ Если кратко: перестать баловаться лёгким дофамином.

Наш мозг формирует приоритеты во многом исходя из того, какое количество дофамина ...</description><pubDate>Fri, 24 May 2024 10:03:10 GMT</pubDate><content:encoded>&lt;p&gt;Сегодня посоветую одну довольно интересную статью (не зря же она была написана в мой день рождения).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/companies/beeline_cloud/articles/813225/&quot;&gt;&lt;strong&gt;Как обхитрить мозг и заставить его полюбить сложные задачи [Дофаминовый детокс]&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;⛔ &lt;strong&gt;Если кратко:&lt;/strong&gt; перестать баловаться лёгким дофамином.&lt;/p&gt;
&lt;p&gt;Наш мозг формирует приоритеты во многом исходя из того, какое количество дофамина он предполагает получить от выполнения какой-либо задачи.Если некая конкретная деятельность высвобождает слишком мало дофамина, у человека будет меньше мотивации заниматься ею.&lt;/p&gt;
&lt;p&gt;В современном мире, наполненном цифровыми технологиями, наш мозг ежедневно насыщается неоправданным количеством дофамина, хотя мы об этом даже не подозреваем. Привыкнув к постоянно высокому уровню дофамина, организм будет считать это состояние новой нормой, к которой необходимо стремиться всеми способами (гомеостаз). Сложные задачи приносят меньше дофамина чем покупки на WB, поэтому от них наступает скука и рука так и тянется к телефону.&lt;/p&gt;
&lt;p&gt;❓ Напрашивается закономерный вопрос: что делать, если ты уже попал в дофаминовую ловушку?&lt;/p&gt;
&lt;p&gt;💡 &lt;strong&gt;Ответ прост:&lt;/strong&gt; проведите дофаминовую детоксикацию.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Выделите день, в течение которого никаких «высокодофаминовых» активностей происходить не будет. Избегайте интернета, любых гаджетов, например, смартфона или компьютера. Ну или постарайтесь лимитировать такие активности.&lt;/li&gt;
&lt;li&gt;Вознаграждайте себя «высокодофаминовыми» активностями, после выполнения «скучных» дел. Например, за каждый час работы позвольте себе 10-15 минут «высокодофаминового» отдыха в конце дня.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Именно так работает дофаминовая детоксикация. Вы лишаетесь всех привычных удовольствий, поэтому через какое-то время любая деятельность начинает выглядеть привлекательно. Проще говоря, вам становится скучно. И на фоне ничегонеделания любая, даже самая банальная задача, становится источником заветного дофамина.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;А я пока пробую такие способы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Отписался от всех новостных каналов (третья попытка за 2 года)&lt;/li&gt;
&lt;li&gt;Первый час после пробуждения не беру в руки телефон&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Теперь бы ещё пиво пореже пить, но не всё же сразу 🍻)&lt;/p&gt;
&lt;p&gt;#fridyareading #burnout&lt;/p&gt;</content:encoded></item><item><title>🏗️ Паттерн “Простая фабрика”</title><link>https://cherkashin.dev/posts/205/</link><guid isPermaLink="true">https://cherkashin.dev/posts/205/</guid><description>🏗️ Паттерн “Простая фабрика”

Ранее я писал:

об абстракциии о полиморфизме

Логическое продолжение этой “базы” — паттерн “простая фабрика”. Он является более простой альтернативой для порождающих паттернов:

фабричный методабстрактная фабрика

По ощущению, используется гораздо чаще, чем его старшие братья (на нём дер...</description><pubDate>Wed, 22 May 2024 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🏗️&lt;/strong&gt; &lt;strong&gt;Паттерн “Простая фабрика”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ранее я писал:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/167&quot;&gt;об абстракции&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/192&quot;&gt;и о полиморфизме&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Логическое продолжение этой “базы” — паттерн “простая фабрика”. Он является более простой альтернативой для порождающих паттернов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;фабричный метод&lt;/li&gt;
&lt;li&gt;абстрактная фабрика&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;По ощущению, используется гораздо чаще, чем его старшие братья (на нём держится весь полиморфизм 😄).&lt;/p&gt;
&lt;p&gt;По сути паттерн представляет собой простой метод, который принимает на вход параметры, и на основе параметров определяет, объект какого типа можно создать.&lt;/p&gt;
&lt;p&gt;Выглядит следующим образом:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; createGitService&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;host&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;token&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; GitService&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  switch&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (type) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;Gitlab&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; GitlabService&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(host, token);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;Gitea&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; GiteaService&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(host, token);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    default&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;💡 Что нам это даёт?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Упрощает код, когда нужно избежать прямых зависимостей от конкретных классов;&lt;/li&gt;
&lt;li&gt;Позволяет инкапсулировать логику создания объектов, ведь логика может быть сложнее, чем простая передача параметров в конструктор.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Этот же паттерн используется внутри хорошо известного вам &lt;code&gt;document.createElement(&quot;div&quot;)&lt;/code&gt; метода. Мы передаём название тега, а метод создаёт тег нужного нам типа.&lt;/p&gt;
&lt;p&gt;Как-нибудь расскажу, как он работает под капотом в Хроме.&lt;/p&gt;
&lt;p&gt;#patterns #essential #oop&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded></item><item><title>У hitch на хабре вышло небольшое интервью со мной. Рассказал, как я нашёл первую работу и устроился…</title><link>https://cherkashin.dev/posts/204/</link><guid isPermaLink="true">https://cherkashin.dev/posts/204/</guid><description>У hitch на хабре вышло небольшое интервью со мной. Рассказал, как я нашёл первую работу и устроился в американскую компанию, без знания английского (Босс, если ты это читаешь — спасибо тебе ❤️).

#about_me #habr</description><pubDate>Mon, 20 May 2024 10:39:42 GMT</pubDate><content:encoded>&lt;p&gt;У hitch на &lt;a href=&quot;https://habr.com/ru/companies/hitch_outstaff/articles/815515/&quot;&gt;хабре вышло небольшое интервью со мной&lt;/a&gt;. Рассказал, как я нашёл первую работу и устроился в американскую компанию, без знания английского (Босс, если ты это читаешь — спасибо тебе ❤️).&lt;/p&gt;
&lt;p&gt;#about_me #habr&lt;/p&gt;</content:encoded></item><item><title>🎉 Шорт-листы &quot;Технотекста 2023&quot; на Хабре</title><link>https://cherkashin.dev/posts/203/</link><guid isPermaLink="true">https://cherkashin.dev/posts/203/</guid><description>🎉 Шорт-листы &quot;Технотекста 2023&quot; на Хабре

Хабр каждый год организует конкурс лучших статей, где может поучаствовать любой автор, написавший статью в текущем году.

Сегодня хабр опубликовал список финалистов куда попало порядка 300 статей. Если не знаете, что почитать пока гоняются ваши тесты, переходите сюда и выбирай...</description><pubDate>Wed, 15 May 2024 12:47:07 GMT</pubDate><content:encoded>&lt;p&gt;🎉 &lt;a href=&quot;https://habr.com/ru/companies/habr/articles/814357/&quot;&gt;Шорт-листы “Технотекста 2023” на Хабре&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Хабр каждый год организует конкурс лучших статей, где может поучаствовать любой автор, написавший статью в текущем году.&lt;/p&gt;
&lt;p&gt;Сегодня хабр опубликовал список финалистов куда попало порядка 300 статей. Если не знаете, что почитать пока гоняются ваши тесты, переходите &lt;a href=&quot;https://habr.com/ru/companies/habr/articles/814357/&quot;&gt;сюда&lt;/a&gt; и выбирайте понравившуюся статью.&lt;/p&gt;
&lt;p&gt;В этом году, в финал попала и мою статья &lt;a href=&quot;https://habr.com/ru/articles/725460/&quot;&gt;Интегрируем Яндекс Музыку в Visual Studio Code&lt;/a&gt;, обязательно прочтите, если ещё этого не сделали.&lt;/p&gt;
&lt;p&gt;#habr&lt;/p&gt;</content:encoded></item><item><title>Сегодня мне 2️⃣8️⃣, примерно как седых волос на моей голове. С недавних пор у нас в компании дают…</title><link>https://cherkashin.dev/posts/202/</link><guid isPermaLink="true">https://cherkashin.dev/posts/202/</guid><description>Сегодня мне 2️⃣8️⃣, примерно как седых волос на моей голове. С недавних пор у нас в компании дают выходной на ДР, поэтому сегодня я гуляю по Сочи, пью пока что только кофе, спокойно пишу этот пост и смотрю как работает моя жена 😃.

Можете начинать желать мне счастья, здоровья, а если бустанёте канал или порекомендуете...</description><pubDate>Wed, 08 May 2024 11:28:03 GMT</pubDate><content:encoded>&lt;p&gt;Сегодня мне 2️⃣8️⃣, примерно как седых волос на моей голове. С недавних пор у нас в компании дают выходной на ДР, поэтому сегодня я гуляю по Сочи, пью пока что только кофе, спокойно пишу этот пост и смотрю как работает моя жена 😃.&lt;/p&gt;
&lt;p&gt;Можете начинать желать мне счастья, здоровья, а если &lt;a href=&quot;https://t.me/cherkashindev?boost&quot;&gt;бустанёте канал&lt;/a&gt; или порекомендуете какой-нибудь курс по программированию, то будет вообще замечательно 😉.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Одной из моих целей на год было набрать 1000 подписчиков в этом канале, и вот вчера &lt;a href=&quot;https://t.me/web_platform&quot;&gt;Виталий Зюзин&lt;/a&gt; легким движением руки выполнил мою цель на год. Он создал &lt;a href=&quot;https://www.notion.so/Inbox-776ea392365e47c68446e05c2b45acbc?pvs=21&quot;&gt;папку с телеграмм каналами о фронтенде,&lt;/a&gt; которая завирусилась и вот нас уже 1300+, обязательно забирайте папку себе и выбирайте каналы, которые вам по душе.&lt;/p&gt;
&lt;p&gt;Всем с кем ещё не знакомы — привет, меня зовут Саша 👋, живу в маленьком и уютном Курске. В разработке я примерно 8 лет и почти 7 из них я работаю в американской компании &lt;a href=&quot;https://decisions.com/&quot;&gt;Decisions.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;📝 Время от времени пишу на Хабр:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/725460/&quot;&gt;Интегрируем Яндекс Музыку в Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/754248/&quot;&gt;Бессильный сборщик мусора или неуправляемая память в .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/696416/&quot;&gt;Система личного планирования в Notion. Эпизод 1 — Инбокс&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✏️ На канале в основном пишу о своём опыте, а по пятницам рекомендую доклады и статьи #fridayreading. Вот некоторые посты, которые могут быть полезны:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/110&quot;&gt;Проверка именования файлов и папок с помощью плагина eslint-plugin-import&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/166&quot;&gt;React – Compound Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/142&quot;&gt;Именование юнит тестов&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/135&quot;&gt;Обязан ли разработчик развиваться&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/129&quot;&gt;Где проводить live-coding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если у вас будут вопросы или просто хочется поболтать — обязательно пишите 👋.&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;
&lt;p&gt;#about_me&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-202-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-202-1.jpg"/></item><item><title>🧑‍💻 Giga Code</title><link>https://cherkashin.dev/posts/197/</link><guid isPermaLink="true">https://cherkashin.dev/posts/197/</guid><description>🧑‍💻 Giga Code

Месяц назад я отключил Codeium и честно начал тестировал GigaCode (альтернативу Copilot от Сбера). Но похоже придётся переключаться обратно, GigaCode ещё сыроват…

Он, конечно, полезен, и действительно иногда упрощает написание кода, да и вообще круто, что появляются такие отечественные продукты.

Но п...</description><pubDate>Mon, 06 May 2024 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🧑‍💻 Giga Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Месяц назад я отключил &lt;a href=&quot;https://t.me/cherkashindev/153&quot;&gt;Codeium&lt;/a&gt; и честно начал тестировал &lt;a href=&quot;https://gigacode.ru/#/instruction/961d9cc0-98c5-11ee-b9d1-0242ac120002&quot;&gt;GigaCode&lt;/a&gt; (альтернативу Copilot от Сбера). Но похоже придётся переключаться обратно, GigaCode ещё сыроват…&lt;/p&gt;
&lt;p&gt;Он, конечно, полезен, и действительно иногда упрощает написание кода, да и вообще круто, что появляются такие отечественные продукты.&lt;/p&gt;
&lt;p&gt;Но пока то и дело (ну очень часто) возникает ощущение, что GigaCode путается под ногами, и мешает писать код, а вовсе не помогает (карточка 4):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Он то и дело вставляет ненужные закрывающие скобки и кавычки, которые VS Code уже вставил за меня.&lt;/li&gt;
&lt;li&gt;Другая надоедливая ситуация — он не может уследить, что я уже написал часть слова и предлагает вставить её ещё раз.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем, пока ждём улучшенной версии …&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-197-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-197-1.jpg"/></item><item><title>📖 Cohesion и Coupling: отличия</title><link>https://cherkashin.dev/posts/196/</link><guid isPermaLink="true">https://cherkashin.dev/posts/196/</guid><description>📖 Cohesion и Coupling: отличия

Сегодня посоветую короткую статью, чтобы наконец-то разобраться что есть что.

🛑 Основные моменты

Нужно стремиться к достижению low coupling (низкой связанности) и high cohesion (высокого сцепления)Cohesion — степень, в которой часть кодовой базы образует логически единую атомарную ед...</description><pubDate>Fri, 26 Apr 2024 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;a href=&quot;https://habr.com/ru/articles/568216/&quot;&gt;Cohesion и Coupling: отличия&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Сегодня посоветую короткую статью, чтобы наконец-то разобраться что есть что.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🛑 Основные моменты&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Нужно стремиться к достижению low coupling (низкой связанности) и high cohesion (высокого сцепления)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cohesion&lt;/strong&gt; — степень, в которой часть кодовой базы образует логически единую атомарную единицу — блок.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coupling&lt;/strong&gt; — степень взаимосвязи между этими блоками.&lt;/li&gt;
&lt;li&gt;Блок здесь необязательно является классом. Это может быть метод, класс, группа классов или даже модуль: понятия cohesion и coupling применимы на разных уровнях.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Высокий cohesion&lt;/strong&gt; означает хранение связанных друг с другом частей кода в одном месте.
&lt;ul&gt;
&lt;li&gt;Например, мы храним код работы с пользователями в одном месте, и это может быть как стандартный MVC контроллер, так и отдельный микросервис.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;В то же время &lt;strong&gt;низкий coupling&lt;/strong&gt; заключается в максимально возможном разделении несвязанных частей кодовой базы.
&lt;ul&gt;
&lt;li&gt;Например, &lt;code&gt;react&lt;/code&gt; и &lt;code&gt;react-dom&lt;/code&gt; хранятся в разных пакетах, благодаря чему мы можем использовать &lt;code&gt;react-native&lt;/code&gt; вместо &lt;code&gt;react-dom&lt;/code&gt; и писать нативные приложения.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;В отличие от такого показателя, как &lt;a href=&quot;https://en.wikipedia.org/wiki/Cyclomatic_complexity&quot;&gt;цикломатическая сложность&lt;/a&gt;, степень cohesion  и coupling не может быть измерена напрямую.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ℹ️ Понятие cohesion похоже на &lt;strong&gt;Принцип единственной ответственности&lt;/strong&gt;, который утверждает, что у класса должна быть одна ответственность, что аналогично тому, что делает код с высоким cohesion. Разница здесь в том, что высокий cohesion необязательно означает, что код должен иметь только одну ответственность. Можно сказать, что Принцип единственной ответственности в этом смысле более строгий.&lt;/p&gt;
&lt;p&gt;#essential #fridayreading&lt;/p&gt;</content:encoded></item><item><title>Несмотря на то, что с балетом у меня натянутые отношения (предыдущие пару раз я еле досидел до…</title><link>https://cherkashin.dev/posts/195/</link><guid isPermaLink="true">https://cherkashin.dev/posts/195/</guid><description>Несмотря на то, что с балетом у меня натянутые отношения (предыдущие пару раз я еле досидел до конца и грозился, чтобы я ещё раз?!), жена уговорила меня поехать в Москву в Большой театр на Лебединое озеро.

Но я решил, что хорошо должно быть не только ей, но и мне. И я отправился в Москву на день раньше и посетить конф...</description><pubDate>Wed, 24 Apr 2024 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;Несмотря на то, что с балетом у меня натянутые отношения (предыдущие пару раз я еле досидел до конца и грозился, чтобы я ещё раз?!), жена уговорила меня поехать в Москву в Большой театр на Лебединое озеро.&lt;/p&gt;
&lt;p&gt;Но я решил, что хорошо должно быть не только ей, но и мне. И я отправился в Москву на день раньше и посетить конференцию Teamly по управлению знаниями.&lt;/p&gt;
&lt;p&gt;Если кто-то не знает — Teamly, это 🇷🇺 российский аналог Notion и Confluence. Каждые пол года компания организовывает бесплатную конференцию, где рассказывает о новой версии продукта и о важности управления знаниями в целом. Конференция была на уровне, что в принципе &lt;a href=&quot;https://youtu.be/Gnq3u6-1Tl8?t=1806&quot;&gt;видно по качеству записи трансляции&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ℹ️ Вот некоторые тезисы, из докладов спикеров:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Чем больше компания — тем больше пользы от системы управления знаниями.&lt;/li&gt;
&lt;li&gt;Если в вашей компании много департаментов — внедрение можно начать с «департаментов-энтузиастов», которые любят внедрять что-то новое. Так будет легче начать внедрение.&lt;/li&gt;
&lt;li&gt;Проект нужно разрабатывать не с конца, а с начала. Например, сначала следует убедиться, что вы можете получить данные для системы, до того как приступить к её разработке. Иначе вы рискуете потратить много времени, денег и сил.&lt;/li&gt;
&lt;li&gt;Всем нам сложно делиться своими провалами, поэтому важно в компании выстраивать культуру так, чтобы сотрудники могли безболезненно о них говорить. Тут поможет встреча &lt;strong&gt;Fails nights&lt;/strong&gt;, на которой, например, раз в квартал сотрудники могут рассказать о своих факапах, а остальные бы могли учиться на чужих ошибках. Подробнее в &lt;a href=&quot;https://vc.ru/hr/114396-friday-wins-i-fails-night-kak-v-miro-delyatsya-uspehami-i-provalami&quot;&gt;статье Miro&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Если благодаря работе у сотрудников закрываются их потребности, например, они выступают на внутренних митапах или делятся знаниями, то они более лояльны компании и не захотят уходить к конкурентам.&lt;/li&gt;
&lt;li&gt;В Teamly можно реализовать поиск &lt;a href=&quot;https://youtu.be/Gnq3u6-1Tl8?t=2686&quot;&gt;сотрудника по компетенциям&lt;/a&gt;. У каждого сотрудника есть личная страница, на ней указываются навыки, а система позволяет искать по этим навыкам. Например, если вам нужен эксперт по Google Sheets и MongoDB, то вы можете легко его найти. Основное преимущество в том, что вся информация хранится в одном месте. Буквально на прошлой неделе в нашей компании решили составить подобный список в Google Sheets, и я уверен, со временем он потеряется и никто его не найдёт.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🔥 Отдельного внимания заслуживает &lt;strong&gt;Гарретт Джонстон&lt;/strong&gt;, &lt;a href=&quot;https://youtu.be/Gnq3u6-1Tl8?t=9552&quot;&gt;его выступление рекомендую посмотреть полностью&lt;/a&gt;. Оно может показаться своеобразным, но внимания точно заслуживает.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Основной тезис его выступления:&lt;/strong&gt; чтобы бизнес был более успешным, нужно перейти от клиентоориентированного подхода, к клиентоцентричному.&lt;/p&gt;
&lt;p&gt;🔍  Например, рыболовный магазин с продавцами знающими своё дело и качественными удочками и снастями — клиентоориентированный бизнес. А если сюда добавить — индивидуальный подбор снастей, выбор локации для рыбной ловли и обучение рыболовству — то бизнес станет клиентоцентричным. Иными словами такой бизнес будет создавать рыболовов, что будет приносить ему больше денег.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt;
От балета удовольствия я особо не получил, а обзор новых функций Teamly вы можете посмотреть &lt;a href=&quot;https://youtu.be/Gnq3u6-1Tl8?t=5580&quot;&gt;здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#conference #teamly&lt;/p&gt;</content:encoded></item><item><title>Вот вам наглядное представление как выглядит закомментированный код - как этот &quot;закомментированный&quot;…</title><link>https://cherkashin.dev/posts/194/</link><guid isPermaLink="true">https://cherkashin.dev/posts/194/</guid><description>Вот вам наглядное представление как выглядит закомментированный код - как этот &quot;закомментированный&quot; дорожный знак 😁.

Ну и вдогонку анекдот от ChatGPT в стиле советских анекдотов:

— Товарищи программисты, почему закомментированный код всегда остаётся закомментированным?
— Потому что он как легендарная пятилетка - все...</description><pubDate>Fri, 19 Apr 2024 08:19:54 GMT</pubDate><content:encoded>&lt;p&gt;Вот вам наглядное представление как выглядит закомментированный код - как этот “закомментированный” дорожный знак 😁.&lt;/p&gt;
&lt;p&gt;Ну и вдогонку анекдот от ChatGPT в стиле советских анекдотов:&lt;/p&gt;
&lt;p&gt;— Товарищи программисты, почему закомментированный код всегда остаётся закомментированным?
— Потому что он как легендарная пятилетка - всегда в планах, но никогда не реализуется!&lt;/p&gt;
&lt;p&gt;#meme&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-194-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-194-1.jpg"/></item><item><title>🗨️ Скорость отдельно взятого разработчика важна, но она не так важна, как скорость всей команды.</title><link>https://cherkashin.dev/posts/193/</link><guid isPermaLink="true">https://cherkashin.dev/posts/193/</guid><description>🗨️ Скорость отдельно взятого разработчика важна, но она не так важна, как скорость всей команды.

Цитата взята из гайда гугла о код ревью, а конкретно из статьи о том почему код ревью должно быть быстрым.

https://google.github.io/eng-practices/review/reviewer/speed.html

#codereview #weekphrase</description><pubDate>Wed, 17 Apr 2024 08:03:23 GMT</pubDate><content:encoded>&lt;p&gt;🗨️ &lt;strong&gt;Скорость отдельно взятого разработчика важна, но она не так важна, как скорость всей команды.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Цитата взята из гайда гугла о код ревью, а конкретно из статьи о том почему код ревью должно быть быстрым.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://google.github.io/eng-practices/review/reviewer/speed.html&quot;&gt;https://google.github.io/eng-practices/review/reviewer/speed.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#codereview #weekphrase&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-193-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-193-1.jpg"/></item><item><title>​​Полиморфизм</title><link>https://cherkashin.dev/posts/192/</link><guid isPermaLink="true">https://cherkashin.dev/posts/192/</guid><description>​​Полиморфизм

Полиморфизм в программировании — это способность объектов принимать множество форм. Это означает, что один и тот же код может работать с разными типами данных.

Пример 1️⃣

Допустим, мы пишем графический редактор, и нам нужно добавить возможность экспортировать элементы в svg формате (как в excalidraw.co...</description><pubDate>Mon, 15 Apr 2024 09:00:07 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/f26db6721db56cfc0a50b.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Полиморфизм&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Полиморфизм в программировании — это способность объектов принимать множество форм. Это означает, что один и тот же код может работать с разными типами данных.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пример 1️⃣&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Допустим, мы пишем графический редактор, и нам нужно добавить возможность экспортировать элементы в svg формате (как в &lt;a href=&quot;https://excalidraw.com/&quot;&gt;excalidraw.com&lt;/a&gt;). Напишем метод, который экспортирует массив выделенных элементов в SVG:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ISvgItem&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;  toSvg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; exportToSvg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;items&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; ISvgItem&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[]) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt; return&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; `&amp;#x3C;svg&gt;${&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;items&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; svg&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;toSvg&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;()).&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&amp;#x3C;/svg&gt;`&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;В данном случае, тот самый объект, который можем принимать &lt;strong&gt;множество форм&lt;/strong&gt; — &lt;strong&gt;параметр `items`&lt;/strong&gt;, так как в этом массиве могут находиться элементы разных типов. Единственное условие — все они должны реализовывать интерфейс &lt;code&gt;ISvgItem&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Реализуем парочку таких типов: круг и квадрат.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Square&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; implements&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ISvgItem&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    constructor&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; side&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    toSvg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;     return&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; `&amp;#x3C;rect &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;         x=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;         y=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;         width=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;side&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;         height=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;side&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot; &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      /&gt;`&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Circle&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; implements&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; ISvgItem&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    constructor&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; radius&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) { }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    toSvg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; `&amp;#x3C;circle x=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot; y=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot; r=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;radius&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}&quot; /&gt;`&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Наш метод &lt;code&gt;exportToSvg&lt;/code&gt; может работать с экземплярами обоих классов:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;exportToSvg&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;([&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Square&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;40&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Circle&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;25&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;В этом примере, когда код работает с объектами, он не знает точно, какой объект будет передан в качестве параметра. Но он точно знает, что у объекта будет метод &lt;code&gt;toSvg()&lt;/code&gt;, это и есть полиморфизм.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пример&lt;/strong&gt; 2️⃣&lt;/p&gt;
&lt;p&gt;Ваше приложение может работать как с PostgreSQL, так и с MSSQL, всё зависит от конфигурации, которую задал пользователь.&lt;/p&gt;
&lt;p&gt;В таком случае мы выделяем абстракцию (абстрактный класс или интерфейс) &lt;code&gt;DataBaseConnection&lt;/code&gt;, и всё приложение работает именно с этой абстракцией, а не с конкретной реализацией.&lt;/p&gt;
&lt;p&gt;В таком случае создаваться &lt;code&gt;DataBaseConnection&lt;/code&gt; скорее всего будет с помощью паттерна “фабрика”, но об этом как-нибудь в другой раз.&lt;/p&gt;
&lt;p&gt;📌 Я бы сказал, что полиморфизм — это логическое продолжение &lt;a href=&quot;https://t.me/cherkashindev/167&quot;&gt;абстракции&lt;/a&gt;, без которого невозможно было бы реализовать большинство паттернов проектирования.&lt;/p&gt;
&lt;p&gt;#essential #oop&lt;/p&gt;</content:encoded></item><item><title>Время ожидания — это «процент занятого времени», разделённый на «процент свободного»</title><link>https://cherkashin.dev/posts/191/</link><guid isPermaLink="true">https://cherkashin.dev/posts/191/</guid><description>Время ожидания — это «процент занятого времени», разделённый на «процент свободного»

Это фраза из книги Проект «Феникс»”

📖 Вот небольшой отрывок:

Время ожидания — это «процент занятого времени», разделённый на «процент свободного».

Другими словами, если ресурс загружен на пятьдесят процентов, то он на пятьдесят пр...</description><pubDate>Thu, 11 Apr 2024 08:04:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Время ожидания — это «процент занятого времени», разделённый на «процент свободного»&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Это фраза из книги &lt;a href=&quot;https://t.me/cherkashindev/78&quot;&gt;Проект «Феникс»”&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;📖 Вот небольшой отрывок:&lt;/p&gt;
&lt;p&gt;Время ожидания — это «процент занятого времени», разделённый на «процент свободного».&lt;/p&gt;
&lt;p&gt;Другими словами, если ресурс загружен на пятьдесят процентов, то он на пятьдесят процентов свободен. Время ожидания равняется пятидесяти процентам, разделённым на пятьдесят процентов, то есть единица времени. Назовём её, например, один час.&lt;/p&gt;
&lt;p&gt;Итак, в среднем наше задание будет стоять в очереди один час, прежде чем будет выполнено. С другой стороны, если какой-то ресурс на девяносто процентов загружен, время ожидания равняется девяноста процентам, разделённым на десять процентов, то есть 9 часам.&lt;/p&gt;
&lt;p&gt;Другими словами, наше задание будет ждать в очереди в девять раз дольше чем в том случае, когда ресурс свободен на пятьдесят процентов.&lt;/p&gt;
&lt;p&gt;В случае с заданием для «Феникса», у нас есть семь инстанций, в каждой из которых сотрудники заняты на девяносто процентов. В таком случае наше задание будет ждать в очереди перед каждым из семи шагов по девять часов…&lt;/p&gt;
&lt;p&gt;🙀 Шестьдесят три часа — только время ожидания в очереди.&lt;/p&gt;
&lt;p&gt;👆Из этого графика следует, что всем нужно свободное время, время «холостого хода».&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;⚠️ Если все в команде заняты высокоприоритетными делами и не имеют ни секунды свободного времени, то общее время разработки увеличивается:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;не будет времени помочь коллеге&lt;/li&gt;
&lt;li&gt;некогда будет сделать код ревью&lt;/li&gt;
&lt;li&gt;на документацию тоже не будет времени&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;всё это увеличивает время разработки. А помимо этого, всегда возникает «незапланированная работа» в виде багов и хот фиксов.&lt;/p&gt;
&lt;p&gt;#weekphrase #planning&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-191-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-191-1.jpg"/></item><item><title>XOR — исключающее или</title><link>https://cherkashin.dev/posts/190/</link><guid isPermaLink="true">https://cherkashin.dev/posts/190/</guid><description>XOR — исключающее или

Пару раз в год в нашем C# коде я встречаю оператор ^ и впадаю в ступор 🤦‍♂️. Через минуту другую я вспоминаю, что оператор называется “исключающее или” или  XOR. Потом, проходит ещё пара минут (на самом деле больше) и я вспоминаю, как он работает и для чего применяется. Поэтому сегодня я решил н...</description><pubDate>Mon, 08 Apr 2024 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;XOR — исключающее или&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Пару раз в год в нашем C# коде я встречаю оператор &lt;code&gt;^&lt;/code&gt; и впадаю в ступор 🤦‍♂️. Через минуту другую я вспоминаю, что оператор называется “исключающее или” или  &lt;code&gt;XOR&lt;/code&gt;. Потом, проходит ещё пара минут (на самом деле больше) и я вспоминаю, как он работает и для чего применяется. Поэтому сегодня я решил написать пост, чтобы &lt;del&gt;моим преподавателям не было стыдно&lt;/del&gt; запомнить этот оператор раз и навсегда.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1️⃣ Как работаете XOR?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Тут всё просто XOR - это сравнение, если A и B равны, то получаем &lt;code&gt;0&lt;/code&gt;, если разные &lt;code&gt;1&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
| A | B | A XOR B |
|---|---|---------|
| 0 | 0 |    0    |
| 0 | 1 |    1    |
| 1 | 0 |    1    |
| 1 | 1 |    0    |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2️⃣ Перечисления — Битовые флаги&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Каждое значение, представляет собой степень двойки (один бит), что помогает удобно хранить и передавать несколько значений.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;cs&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;Flags&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;enum&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; Permissions&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    None&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,                    &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// 000&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    Read&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,                    &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// 001&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    Write&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,                   &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// 010&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;    Execute&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;                  // 100&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    All &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Read &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Write &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Execute &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// 111 &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;3️⃣ &lt;strong&gt;Применение XOR с битовыми флагами:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Оператор XOR часто используется для добавления и удаления определенных битовых флагов.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;cs&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;Permissions&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; myPermissions&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Permissions.Read &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Permissions.Execute;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// Добавление прав на запись&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;myPermissions &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;^=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Permissions.Write;   &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// 101 ^ 010 = 111&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// Удаление прав на выполнение&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;myPermissions &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;^=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; Permissions.Execute; &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// 111 ^ 100 = 011 &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;#essential #csharp&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded></item><item><title>Сегодня я вам принёс важную статью “Решение, которое нужно принять, чтобы не жалеть о жизни через…</title><link>https://cherkashin.dev/posts/189/</link><guid isPermaLink="true">https://cherkashin.dev/posts/189/</guid><description>Сегодня я вам принёс важную статью “Решение, которое нужно принять, чтобы не жалеть о жизни через 30 лет”. Важная — потому что она не о программировании, а о нашей с вами жизни в целом. В статье рассказывается как стоит жить сейчас, чтобы на смертном одре не пожалеть о прожитом.

⚠️ Главная проблема, о которой говорит ...</description><pubDate>Fri, 05 Apr 2024 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;Сегодня я вам принёс важную статью &lt;a href=&quot;https://habr.com/ru/companies/alconost/articles/346020/&quot;&gt;“Решение, которое нужно принять, чтобы не жалеть о жизни через 30 лет”.&lt;/a&gt; Важная — потому что она не о программировании, а о нашей с вами жизни в целом. В статье рассказывается как стоит жить сейчас, чтобы на смертном одре не пожалеть о прожитом.&lt;/p&gt;
&lt;p&gt;⚠️ Главная проблема, о которой говорит автор, заключается в том, что мы гонимся за краткосрочными успехами, которые дают быстрый результат, что позволяет нам почувствовать собственную значимость. В погоне за этим “лёгким дофамином” мы забываем думать о будущем и строить планы, чтобы добиться того, чего мы действительно хотим. Так мы отдаляемся от того, о чём действительно мечтаем.&lt;/p&gt;
&lt;p&gt;ℹ️ За примерами далеко ходить не нужно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Люди не хотят быть одиноки, но уделяют работе всё своё время, забывая о семье, из-за чего семьи разваливаются&lt;/li&gt;
&lt;li&gt;Не хотят умирать “преждевременно” — но выбирают пиво с чипсами, вместо ЗОЖ&lt;/li&gt;
&lt;li&gt;Не хотят быть безработными или бедными — но смотрят очередную серию сериала, вместо обучения&lt;/li&gt;
&lt;li&gt;Не хотят быть глупыми — но не уделяют времени чтению&lt;/li&gt;
&lt;li&gt;Не планируют жить в постоянном нервном напряжении — но игры и отдых кажутся пустой тратой времени&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✅ Чтобы перестать думать в краткосрочной перспективе и научиться видеть долгосрочную нужно понять ключевой принцип “перспективных занятий”.  &lt;strong&gt;Перспективные занятия&lt;/strong&gt; — занятия, которые окупаются в долгосрочной перспективе, но не всегда в краткосрочной.&lt;/p&gt;
&lt;p&gt;🧠 Автор статьи советует уделять 10 часов в неделю “перспективным занятиям”. Однако это не так-то просто, ведь чтобы увидеть результаты, потребуется много времени и возможно даже не один год.  Лучший способ найти время для перспективных занятий — сделать выделяемые им часы неприкосновенными и ввести их в привычку.&lt;/p&gt;
&lt;p&gt;#fridayreading&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded></item><item><title>🗣 Фраза недели — “Да надо”</title><link>https://cherkashin.dev/posts/188/</link><guid isPermaLink="true">https://cherkashin.dev/posts/188/</guid><description>🗣 Фраза недели — “Да надо”

В честь первого апреля расскажу вам одну историю.

📖  Несколько лет назад во время пандемии скучными вечерами, покуривая кальян, я читал книгу “Программист Прагматик”. Обсуждать всю книгу я конечно же не буду, остановлюсь лишь на одной теме, которая задела меня за живое. Автор описывал, чт...</description><pubDate>Mon, 01 Apr 2024 08:00:04 GMT</pubDate><content:encoded>&lt;p&gt;🗣 &lt;strong&gt;Фраза недели — “Да надо”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В честь первого апреля расскажу вам одну историю.&lt;/p&gt;
&lt;p&gt;📖  Несколько лет назад во время пандемии скучными вечерами, покуривая кальян, я читал книгу “Программист Прагматик”. Обсуждать всю книгу я конечно же не буду, остановлюсь лишь на одной теме, которая задела меня за живое. Автор описывал, что лишь одна фраза может внести полнейший хаос в работу и взаимопонимание коллектива — фраза “мы должны” также известная как “нам надо”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Простой пример:&lt;/strong&gt; на очередном митинге кто-то невзначай произносит “мы должны что-то сделать, чтобы эта страница загружалась за 2 секунды”. После этого митинг продолжается, затем заканчивается, но вам всё ещё непонятно, а кто мы? Кто именно должен это сделать?&lt;/p&gt;
&lt;p&gt;ℹ️ Вот чтобы такого не было, нужно использовать более конкретные и четкие формулировки, которые ясно указывают на ответственность за выполнение задачи. Например, вместо того чтобы говорить “мы должны ускорить загрузку страницы”, лучше сказать “Черкашин, тебе нужно ускорить загрузки страницы в следующем спринте”.&lt;/p&gt;
&lt;p&gt;👨 Не думаю, что мой батя читал эту книгу тайком, пока я кодил, но он сумел превратить недостатки фразы “нам надо” в достоинства. Родители живут в частном доме, и каждый год моя мама говорит отцу “Ваня, отделай крыльцо плиткой”, а он говорит &lt;strong&gt;“Да надо”&lt;/strong&gt; (что означает, делать этого я конечно же не буду), и так уже года 4. Верх дипломатии, вроде и не отказался, но ответственность размыл, сроки тоже туманные.&lt;/p&gt;
&lt;p&gt;Я как истинный сын своего отца, теперь всегда поддерживаю своего тимлида. Если он говорит “Нам нужно …” или “Мы должны”, я отвечаю ему “Да, надо”, в итоге никто этими предложениями не занимается 😄. Это стало своего рода мемом в команде.&lt;/p&gt;
&lt;p&gt;👉 В общем, будьте конкретны в своих предложениях. И ставьте лайки для бати — если пост наберёт 20 лайков батя сделает крыльцо в этом году (но это не точно).&lt;/p&gt;
&lt;p&gt;#weekphrase #meme&lt;/p&gt;</content:encoded></item><item><title>Небольшой список чат ботов, которыми время от времени пользуюсь</title><link>https://cherkashin.dev/posts/187/</link><guid isPermaLink="true">https://cherkashin.dev/posts/187/</guid><description>Небольшой список чат ботов, которыми время от времени пользуюсь

https://chat.openai.com/ — представления не требуетhttps://www.phind.com/ — о phind писал здесьhttps://gemini.google.com/app - AI чат бот от гугла, работает только через VPNhttps://ya.ru/alisadavaypridumaem — чат бот от Яндексаhttps://300.ya.ru/ — краткий...</description><pubDate>Fri, 29 Mar 2024 07:07:03 GMT</pubDate><content:encoded>&lt;p&gt;Небольшой список чат ботов, которыми время от времени пользуюсь&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://chat.openai.com/&quot;&gt;https://chat.openai.com/&lt;/a&gt; — представления не требует&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.phind.com/&quot;&gt;https://www.phind.com/&lt;/a&gt; — о phind писал &lt;a href=&quot;https://t.me/cherkashindev/176&quot;&gt;здесь&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gemini.google.com/app&quot;&gt;https://gemini.google.com/app&lt;/a&gt; - AI чат бот от гугла, работает только через VPN&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ya.ru/alisa_davay_pridumaem&quot;&gt;https://ya.ru/alisa_davay_pridumaem&lt;/a&gt; — чат бот от Яндекса&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://300.ya.ru/&quot;&gt;https://300.ya.ru/&lt;/a&gt; — краткий пересказ, статей и видео от Яндекса&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/gigachat_bot&quot;&gt;https://t.me/gigachat_bot&lt;/a&gt; — чат бот от Сбера&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В Сбере заморочились и реализовали расширение по типу Codeium (&lt;a href=&quot;https://t.me/cherkashindev/153&quot;&gt;о нём писал здесь&lt;/a&gt;) для VS Code и IDE от JetBrains. Скорее всего это связано с запуском ими аналога Github — &lt;a href=&quot;https://gitverse.ru/dashboard&quot;&gt;Gitverse&lt;/a&gt;, и альтернативы Copilot — Gigacode. &lt;a href=&quot;https://gigacode.ru/#/instruction/961d9cc0-98c5-11ee-b9d1-0242ac120002&quot;&gt;Инструкция по установке здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;А какими AI ботами или другими сервисами пользуетесь вы?&lt;/p&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded></item><item><title>#рекомендую_канал</title><link>https://cherkashin.dev/posts/186/</link><guid isPermaLink="true">https://cherkashin.dev/posts/186/</guid><description>#рекомендую_канал

Сегодня решил начать делиться каналами, которые читаю сам, возможно когда-нибудь даже опубликую ссылку на папку с каналами 🤔 , но это не сегодня …

Возможно вы уже знаете Даниэля по его сообществу Фронт.ру, он достаточно молод, и уже успел поработать фронтендером в Сбере и Яндекс Поиске. Даниэль пиш...</description><pubDate>Thu, 28 Mar 2024 07:28:28 GMT</pubDate><content:encoded>&lt;p&gt;#рекомендую_канал&lt;/p&gt;
&lt;p&gt;Сегодня решил начать делиться каналами, которые читаю сам, возможно когда-нибудь даже опубликую ссылку на папку с каналами 🤔 , но это не сегодня …&lt;/p&gt;
&lt;p&gt;Возможно вы уже знаете &lt;a href=&quot;https://t.me/dlents&quot;&gt;Даниэля&lt;/a&gt; по его сообществу &lt;a href=&quot;https://t.me/dlents/5&quot;&gt;Фронт.ру,&lt;/a&gt; он достаточно молод, и уже успел поработать фронтендером в Сбере и Яндекс Поиске. Даниэль пишет интересно и не только о коде, но и о том как работается в самой компании. Возможно, как-нибудь и я решусь написать пару постов о своей работе 😄.&lt;/p&gt;
&lt;p&gt;В этих постах можете познакомиться с тем как проходят первые дни в Яндексе:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/dlents/6&quot;&gt;Прошел первый день в офисе Яндекса&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/dlents/8&quot;&gt;Сегодня было парное программирование&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/dlents/10&quot;&gt;Моя первая таска в проде&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/dlents/22&quot;&gt;Как проходили собеседования в Яндекс?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/dlents/30&quot;&gt;Сегодня ровно месяц как работаю в Яндекс.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/dlents/36&quot;&gt;Закончился мой испытательный срок в Яндексе.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Кстати, сегодня ровно год блогу Даниэля а завтра, год как он работает в Яндексе, поэтому давайте поздравим его подпиской на его канал 🎂.&lt;/p&gt;
&lt;p&gt;@cherkashindev&lt;/p&gt;</content:encoded></item><item><title>Максимальная длина строки в V8</title><link>https://cherkashin.dev/posts/185/</link><guid isPermaLink="true">https://cherkashin.dev/posts/185/</guid><description>Максимальная длина строки в V8

У меня есть небольшой пет проект, для построения различных графиков для пул реквестов, которые показывают кто кому оставляет комментарии, ставит аппрувы и прочее. Бэкенда там нет, фронт ходит в Gitlab или Gitea, выкачивает информацию за указанный период времени и рисует графики.

Чтобы н...</description><pubDate>Mon, 25 Mar 2024 07:02:31 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Максимальная длина строки в V8&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;У меня есть небольшой пет проект, для построения различных графиков для пул реквестов, которые показывают кто кому оставляет комментарии, ставит аппрувы и прочее. Бэкенда там нет, фронт ходит в Gitlab или Gitea, выкачивает информацию за указанный период времени и рисует графики.&lt;/p&gt;
&lt;p&gt;Чтобы не гонят лишний раз данные, я добавил возможность импорта/экспорта. Вроде всё хорошо, но вчера я решил выгрузить данные за 4 года и при экспорте словил &lt;a href=&quot;https://stackoverflow.com/questions/72955514/rangeerror-invalid-string-length-at-array-join&quot;&gt;ошибку&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
JSON.stringify Uncaught RangeError: Invalid string length
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Немного погуглив, нашёл,  что длина строки в V8:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;268.4 мегабайт на 32-битных платформах&lt;/li&gt;
&lt;li&gt;538.8 мегабайт на 64-битных платформах (на М1 похоже такая же)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✅ Решил проблему просто: при экспорте разбиваю мой большой массив, на несколько частей и экспортирую несколько файлов.&lt;/p&gt;
&lt;p&gt;Аналогично не получится считать файл как текст, получите просто пустую строку. &lt;code&gt;readAsArrayBuffer&lt;/code&gt; работает, но попробуй понять как байты преобразовать в строки меньших размеров, да так, чтобы получить валидные JSON объекты.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; reader&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; FileReader&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;reader.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;onload&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(reader.result); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// result будет пустой строкой&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;reader.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;readAsText&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(file);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;В Firefox такой проблемы нет, всё работает.&lt;/p&gt;
&lt;p&gt;#browser #frontend&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-185-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-185-1.jpg"/></item><item><title>⚛️ React 19 — useOptimistic</title><link>https://cherkashin.dev/posts/184/</link><guid isPermaLink="true">https://cherkashin.dev/posts/184/</guid><description>⚛️ React 19 — useOptimistic

useOptimistic — новый хук, который позволяет отобразить “оптимистичное” состояние. Оно называется “оптимистичным”, потому что мы “оптимистично” надеемся, что наш запрос не свалится с ошибкой и после выполнения запроса состояние будет выглядеть именно так.

❓Как используется

В useOptimistic...</description><pubDate>Mon, 18 Mar 2024 07:52:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;⚛️ React 19 — useOptimistic&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;useOptimistic&lt;/code&gt; — новый хук, который позволяет отобразить “оптимистичное” состояние. Оно называется “оптимистичным”, потому что мы “оптимистично” надеемся, что наш запрос не свалится с ошибкой и после выполнения запроса состояние будет выглядеть именно так.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;❓Как используется&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В &lt;code&gt;useOptimistic&lt;/code&gt; передаётся реальное состояние (&lt;code&gt;cart&lt;/code&gt;) и функцию-reducer, для обновления оптимистичного состояния&lt;/li&gt;
&lt;li&gt;Компонент (&lt;code&gt;Cart&lt;/code&gt;) использует “оптимистичное” состояние (&lt;code&gt;optimisticCart&lt;/code&gt;) для рендера&lt;/li&gt;
&lt;li&gt;Перед выполнением запроса обновляется “оптимистичное” состояние&lt;/li&gt;
&lt;li&gt;Когда запрос завершился, нужно обновить реальное состояние&lt;/li&gt;
&lt;li&gt;Как только реальное состояние обновилось, оптимистичное состояние обновится автоматически, так как оно передано в &lt;code&gt;useOptimistic&lt;/code&gt; первым параметром. ⚠️ Поэтому важно следить, чтобы приходило одно и то же состояние.&lt;/li&gt;
&lt;li&gt;Если запрос упал с ошибкой, нужно откатить изменения в оптимистичном состоянии.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ℹ️ Первый вопрос, которым я задался, а в чём отличие от обычного &lt;code&gt;setState&lt;/code&gt;, путём экспериментов, вот что удалось найти:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useOptimistic&lt;/code&gt; работает с формами. Работать с обычной кнопкой в Single Page Application мне не удалось, обновление происходило только после завершения запроса&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useOptimistic&lt;/code&gt; работает только внутри асинхронного обработчика, что логично. Если убрать &lt;code&gt;async/await&lt;/code&gt;, обновление произойдёт только после завершения запроса&lt;/li&gt;
&lt;li&gt;Параметр в &lt;code&gt;useState&lt;/code&gt; используется только для инициализации, и игнорируется в последующих рендерах. &lt;code&gt;useOptimistic&lt;/code&gt; будет сихронизироваться со значением переданным первым параметром.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🤷‍♂️ Очень мало полезного удалось найти о &lt;code&gt;useOptimistic&lt;/code&gt;. Во всех статьях и видео тривиальные примеры, нигде не рассказывается как обрабатывать более сложные ситуации:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Как обновлять оптимистичное состояние, если запустить несколько запросов одновременно?&lt;/li&gt;
&lt;li&gt;Как использовать &lt;code&gt;useOptimistic&lt;/code&gt; в SPA вне форм?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Поэтому пришлось создать пару ишью: &lt;a href=&quot;https://github.com/facebook/react/issues/28574&quot;&gt;раз&lt;/a&gt; и &lt;a href=&quot;https://stackoverflow.com/questions/78178110/does-useoptimistic-works-only-with-forms&quot;&gt;два&lt;/a&gt;. В любом случае, пока &lt;code&gt;useOptimistic&lt;/code&gt; выглядит каким-то низкоуровневым API. Надеюсь скоро появится больше Best Practices по его применению. Если вам есть что добавить — пишите в комментах.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=M61_qswUO6I&amp;#x26;ab_channel=FrontendFirst&quot;&gt;Frontend First — Ep 179 - React Deep Dive: useOptimistic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/reference/react/useOptimistic&quot;&gt;Официальная документация по useOptimistic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/acherkashin/react19-useOptimistic/tree/dev/reducer&quot;&gt;Код из примера тут&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#react #frontend #new&lt;/p&gt;</content:encoded></item><item><title>⚛️ React 19 — use(Promise)</title><link>https://cherkashin.dev/posts/182/</link><guid isPermaLink="true">https://cherkashin.dev/posts/182/</guid><description>⚛️ React 19 — use(Promise)

use — новый хук, который позволяет считывать данные из промиса и при этом интегрирован с Suspense и ErrorBoundary.

ℹ️ Основные моменты:

На этот хук не распространяются правила хуков — его можно использовать внутри циклов и условных операторов.Если мы используем хук use(Promise), то где-то ...</description><pubDate>Wed, 13 Mar 2024 07:24:18 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;⚛️ React 19 — use(Promise)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;use&lt;/code&gt; — новый хук, который позволяет считывать данные из промиса и при этом интегрирован с &lt;code&gt;Suspense&lt;/code&gt; и &lt;code&gt;ErrorBoundary&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;ℹ️ Основные моменты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;На этот хук не распространяются &lt;a href=&quot;https://react.dev/warnings/invalid-hook-call-warning&quot;&gt;правила хуков&lt;/a&gt; — его можно использовать внутри циклов и условных операторов.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Если мы используем хук &lt;code&gt;use(Promise)&lt;/code&gt;, то где-то в родительском компоненте мы должны положить сам промис (не данные как мы делали раньше) в стейт (&lt;code&gt;useState&lt;/code&gt;). Это позволяет избавиться от &lt;code&gt;useEffect&lt;/code&gt;’а, который был нужен, чтобы запросить данные при первом рендере.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Хук интегрирован с &lt;code&gt;Suspense&lt;/code&gt;, поэтому пока промис не разрезолвится — будет показан &lt;code&gt;fallback&lt;/code&gt; объявленный в ближайшем &lt;code&gt;Suspense&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Если промис зареджектился, то будет показан &lt;code&gt;fallback&lt;/code&gt; объявленный в ближайшем &lt;code&gt;ErrorBoundary&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://stackblitz.com/edit/stackblitz-starters-vcsymj?file=src%2FApp.tsx&quot;&gt;Песочница тут&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://react.dev/reference/react/use&quot;&gt;Официальная документация тут&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend #react #new&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-182-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-182-1.jpg"/></item><item><title>⚙️ .editorconfig</title><link>https://cherkashin.dev/posts/180/</link><guid isPermaLink="true">https://cherkashin.dev/posts/180/</guid><description>⚙️ .editorconfig

Вопрос от менти: У меня проблемы с кодировкой. В гитхабе вижу битые символы вместо русских букв. Почему и как исправить?

Ответ: Скорее всего редактор создаёт файлы в кодировке типа “Cyrillic (Windows 1251)”. Чтобы это исправить, нужно пересохранить существующие файлы  в кодировке UTF-8.

А, чтобы нов...</description><pubDate>Wed, 06 Mar 2024 09:39:43 GMT</pubDate><content:encoded>&lt;p&gt;⚙️ &lt;strong&gt;.editorconfig&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Вопрос от менти:&lt;/strong&gt; У меня проблемы с кодировкой. В гитхабе вижу битые символы вместо русских букв. Почему и как исправить?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ответ:&lt;/strong&gt; Скорее всего редактор создаёт файлы в кодировке типа “Cyrillic (Windows 1251)”. Чтобы это исправить, нужно пересохранить существующие файлы  в кодировке UTF-8.&lt;/p&gt;
&lt;p&gt;А, чтобы новые файлы создавались с правильной кодировкой, в корне проекта нужно создать файл &lt;code&gt;.editorconfig&lt;/code&gt;  и указать что все файлы (&lt;code&gt;[*]&lt;/code&gt;) должны иметь кодировку &lt;code&gt;utf-8&lt;/code&gt; (&lt;code&gt;charset = utf-8&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[*]
charset = utf-8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Этот файл поддерживается большинством популярных редакторов кода, поэтому в дальнейшем, когда ты будешь работать в команде, он поможет поддерживать консистентные стили кода.&lt;/p&gt;
&lt;p&gt;В нём же можно настроить отступы, размер табов и прочее. &lt;a href=&quot;https://editorconfig.org/&quot;&gt;Подробнее здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#mentee_question #essential&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-180-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-180-1.jpg"/></item><item><title>👨‍💻 Phind</title><link>https://cherkashin.dev/posts/176/</link><guid isPermaLink="true">https://cherkashin.dev/posts/176/</guid><description>👨‍💻 Phind

В комментариях к прошлому посту о Codeium мне порекомендовали попробовать Phind.

До расширения для VS Code руки ещё не дошли, а вот онлайн версией пользуюсь достаточно регулярно. Очень удобно учитывая, что он бесплатный, генерирует неплохие ответы и не нужно постоянно включать VPN, если вы находитесь в Ро...</description><pubDate>Mon, 04 Mar 2024 07:56:55 GMT</pubDate><content:encoded>&lt;p&gt;👨‍💻 &lt;strong&gt;Phind&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В комментариях к прошлому посту о Codeium мне &lt;a href=&quot;https://t.me/artalog/1176?comment=307378&quot;&gt;порекомендовали попробовать Phind&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;До &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=phind.phind&quot;&gt;расширения для VS Code&lt;/a&gt; руки ещё не дошли, а вот онлайн версией пользуюсь достаточно регулярно. Очень удобно учитывая, что он бесплатный, генерирует неплохие ответы и не нужно постоянно включать VPN, если вы находитесь в России.&lt;/p&gt;
&lt;p&gt;Вначале не мог запомнить название, но потом понял, что &lt;code&gt;phind&lt;/code&gt; — это &lt;code&gt;find&lt;/code&gt; через &lt;code&gt;ph&lt;/code&gt; и всё стало на свои места.&lt;/p&gt;
&lt;p&gt;У Phind есть 2 режима:&lt;/p&gt;
&lt;p&gt;1️⃣ Чат — стандартный чат, аналогичный ChatGPT&lt;/p&gt;
&lt;p&gt;2️⃣ Поиск — phind сгенерирует ответ и покажет ссылки на использованные источники в интернете.&lt;/p&gt;
&lt;p&gt;Также позволяет запустить сгенерированный код в &lt;a href=&quot;https://replit.com/&quot;&gt;Replit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-176-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-176-1.jpg"/></item><item><title>Наконец-то попаду на &quot;Я 💛 Фронтенд&quot; в оффлайне. Трансляция тоже будет.</title><link>https://cherkashin.dev/posts/175/</link><guid isPermaLink="true">https://cherkashin.dev/posts/175/</guid><description>Наконец-то попаду на &quot;Я 💛 Фронтенд&quot; в оффлайне. Трансляция тоже будет.

https://events.yandex.ru/events/ya-love-frontend-2024

#conference</description><pubDate>Sun, 03 Mar 2024 14:42:42 GMT</pubDate><content:encoded>&lt;p&gt;Наконец-то попаду на “Я 💛 Фронтенд” в оффлайне. Трансляция тоже будет.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://events.yandex.ru/events/ya-love-frontend-2024&quot;&gt;https://events.yandex.ru/events/ya-love-frontend-2024&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#conference&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-175-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-175-1.jpg"/></item><item><title>🆙 Кнопки в базах данных Notion</title><link>https://cherkashin.dev/posts/174/</link><guid isPermaLink="true">https://cherkashin.dev/posts/174/</guid><description>🆙 Кнопки в базах данных Notion

Когда-то давно я писал, как  автоматически заполнять Completed Date поле в Notion.

С тех пор много воды утекло, и кажется об использовании Github Actions для этих целей можно забыть.

В Notion уже давно есть кнопки, наконец-то они появились и в базах данных.

Ещё пример

#notion #autom...</description><pubDate>Tue, 27 Feb 2024 08:01:00 GMT</pubDate><content:encoded>&lt;p&gt;🆙 &lt;strong&gt;Кнопки в базах данных Notion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда-то давно &lt;a href=&quot;https://t.me/cherkashindev/58&quot;&gt;я писал, как  автоматически заполнять Completed Date поле в Notion&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;С тех пор много воды утекло, и кажется об использовании Github Actions для этих целей можно забыть.&lt;/p&gt;
&lt;p&gt;В Notion уже давно есть кнопки, наконец-то они появились и в базах данных.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/marianotion/363&quot;&gt;Ещё пример&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#notion #automation&lt;/p&gt;</content:encoded></item><item><title>☁️ Облако слов</title><link>https://cherkashin.dev/posts/173/</link><guid isPermaLink="true">https://cherkashin.dev/posts/173/</guid><description>☁️ Облако слов

Ради интереса решил построить облако слов на основе комментариев в пул реквестах.

Нашёл пару подходящих библиотек:

react-tagcloud — нет типов для тайпскрипта, и облако само по себе выглядит не очень красивоreact-wordcloud — типы есть, облако выглядит неплохо, использовать легко

&lt;ReactWordcloud
  size...</description><pubDate>Mon, 26 Feb 2024 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;☁️ &lt;strong&gt;Облако слов&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ради интереса решил построить облако слов на основе комментариев в пул реквестах.&lt;/p&gt;
&lt;p&gt;Нашёл пару подходящих библиотек:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/madox2/react-tagcloud&quot;&gt;react-tagcloud&lt;/a&gt; — нет типов для тайпскрипта, и облако само по себе &lt;a href=&quot;https://madox2.github.io/react-tagcloud/&quot;&gt;выглядит не очень красиво&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/chrisrzhou/react-wordcloud&quot;&gt;react-wordcloud&lt;/a&gt; — типы есть, облако выглядит неплохо, использовать легко&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;ReactWordcloud&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  size&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;500&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  words&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  maxWords&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;350&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  options&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{ fontSizes: [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;120&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;] }&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  callbacks&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    onWordClick&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: (&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;      onClick&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(e.text);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;#library #react&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-173-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-173-1.jpg"/></item><item><title>​​Уровни абстракции</title><link>https://cherkashin.dev/posts/170/</link><guid isPermaLink="true">https://cherkashin.dev/posts/170/</guid><description>​​Уровни абстракции

Уровни абстракции — одна из самых важных и одновременно самых сложных концепций, понимание которой ведёт к написанию качественного кода.

Методы и функции — один из самых простых примеров, на основе которых можно рассмотреть концепцию уровней абстракции.

ℹ️ Когда мы описываем функцию, то все метод...</description><pubDate>Mon, 19 Feb 2024 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/1349cbfc70396dca7f564.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Уровни абстракции&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Уровни абстракции — одна из самых важных и одновременно самых сложных концепций, понимание которой ведёт к написанию качественного кода.&lt;/p&gt;
&lt;p&gt;Методы и функции — один из самых простых примеров, на основе которых можно рассмотреть концепцию уровней абстракции.&lt;/p&gt;
&lt;p&gt;ℹ️ Когда мы описываем функцию, то все методы, которые мы вызываем внутри должны находиться на один уровень абстракции ниже. В конце концов, функции пишутся прежде всего для разложения более крупной концепции (иначе говоря, имени функции) на последовательность действий на следующем уровне абстракции.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Как понять, что метод написан на разных уровнях абстракции❓&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Когда мы смешиваем уровни абстракции, то функция обрастает большим количеством второстепенных подробностей — деталями с более низкого уровня абстракции&lt;/li&gt;
&lt;li&gt;Если читать код функции, вы найдёте одновременно действия, которые будут отвечать на вопросы “что?” и “как?”:
&lt;ul&gt;
&lt;li&gt;“&lt;strong&gt;что?&lt;/strong&gt;” — более высокий уровень абстракции, тут функция описывает, что мы делаем.&lt;/li&gt;
&lt;li&gt;“&lt;strong&gt;как?&lt;/strong&gt;” — тут будет описано, “как” мы что-то делаем, а чтобы понять что именно, нужно будет напрячь извилины и подумать. И если мы заменим это “как” на функцию, имя которой будет отвечать на вопрос “что”, то всё станет на свои места и  будет на одном уровне абстракции.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;⚠️ Не окрепшим умам главное понять, что метод написанный на “одном уровне абстракции” это то, к чему нужно стремиться, но главное не переусердствовать, ведь не всегда так просто провести грань между уровнями абстракции.&lt;/p&gt;
&lt;p&gt;Но методами это все конечно не ограничивается. Классы тоже могут быть на разных уровнях абстракции, они могут раскладываться по разным библиотекам, и тогда эти библиотеки взаимодействуют между собой только посредством публичного API.  Но подробнее об этом как-нибудь в другой раз.&lt;/p&gt;
&lt;p&gt;Пример на прикреплённой картинке взял &lt;a href=&quot;https://www.c-sharpcorner.com/article/clean-code-single-level-of-abstraction/&quot;&gt;отсюда&lt;/a&gt;, возможно не самый лучший, но суть должно быть понятна.&lt;/p&gt;
&lt;p&gt;Пример от Дядюшки Боба найдёте в комментариях, из него должно стать понятней, что имелось ввиду при описании “что?” и “как?”&lt;/p&gt;
&lt;p&gt;#architecture #cleancode #abstraction&lt;/p&gt;</content:encoded></item><item><title>Яндекс.Музыка уже давно поменяла логотип, поэтому пришло время обновить его и в расширении для VS…</title><link>https://cherkashin.dev/posts/168/</link><guid isPermaLink="true">https://cherkashin.dev/posts/168/</guid><description>Яндекс.Музыка уже давно поменяла логотип, поэтому пришло время обновить его и в расширении для VS Code.

P.S. За иконки спасибо автору Мастерской Программиста 👍</description><pubDate>Sun, 18 Feb 2024 13:37:48 GMT</pubDate><content:encoded>&lt;p&gt;Яндекс.Музыка уже давно поменяла логотип, поэтому пришло время обновить его и в &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=acherkashin.yandex-music-extension&quot;&gt;расширении для VS Code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;P.S. За иконки спасибо автору &lt;a href=&quot;https://t.me/masterskaya_AI/120&quot;&gt;Мастерской Программиста&lt;/a&gt; 👍&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-168-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-168-1.jpg"/></item><item><title>🔮 Абстракция</title><link>https://cherkashin.dev/posts/167/</link><guid isPermaLink="true">https://cherkashin.dev/posts/167/</guid><description>🔮 Абстракция

Когда говорят про ООП, часто забывают о двух вещах:

Это не только инкапсуляция, наследование и полиморфизм, но ещё и абстракцияИнкапсуляция, наследование и полиморфизм не прибиты гвоздями к ООП, особенно инкапсуляция и полиморфизм. Но об этом не сегодня.

Сегодня советую к просмотру видео: Абстракция, у...</description><pubDate>Fri, 16 Feb 2024 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🔮&lt;/strong&gt; &lt;strong&gt;Абстракция&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда говорят про ООП, часто забывают о двух вещах:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Это не только инкапсуляция, наследование и полиморфизм, но ещё и &lt;em&gt;абстракция&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Инкапсуляция, наследование и полиморфизм не прибиты гвоздями к ООП, особенно инкапсуляция и полиморфизм. Но об этом не сегодня.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Сегодня советую к просмотру видео: &lt;a href=&quot;https://www.youtube.com/watch?v=zC5_yy3Ue-k&amp;#x26;ab_channel=ValeryLeontyev&quot;&gt;Абстракция, уровни абстракции&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ℹ️ Основные моменты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Абстракция&lt;/strong&gt; — отвлечение от несущественных сторон, свойств, связей объекта с целью выделения их существенных, закономерных признаков. Иными словами, мы выделяем существенные свойства для нашей конкретной задачи, и не обращаем на несущественные.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Абстрация&lt;/strong&gt; = Интерфейс + Инкапсуляция&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Интерфейс&lt;/strong&gt;  — выделяет существенное&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Инкапсуляция&lt;/strong&gt; — скрывает несущественное&lt;/li&gt;
&lt;li&gt;Абстрагирование нужно для управления сложностью кода, чтобы всё было надёжно, эффективно, расширяемо и поддерживаемо.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;💡 Например, у нас есть квадрат, и для разных задач, нам важны его различные свойства.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если нам важно вычислять его площадь и периметр, то мы говорим, что квадрат — это геометрическая фигура (абстрагируемся). Иначе говоря квадрат реализует интерфейс &lt;code&gt;IGeometricShape&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Если нам важно, чтобы квадрат мог быть сохранён в файл, то мы говорим, что квадрат — сериализуемый, например, в JSON объект, который затем можно записать в файл.  Иначе говоря квадрат реализует интерфейс &lt;code&gt;ISerializable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Аналогично, если нам важно уметь рисовать квадрат на экране, он должен реализовывать интерфейс &lt;code&gt;IDrawable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Ну и где-то у нас есть методы, которые работают с абстракциями &lt;code&gt;IGeometricShape&lt;/code&gt;,  &lt;code&gt;ISerializable&lt;/code&gt; и &lt;code&gt;IDrawable&lt;/code&gt;. Таким образом методы &lt;strong&gt;абстрагированы&lt;/strong&gt; от конкретных реализаций, что увеличивает переиспользуемость кода.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ну и немного от себя, абстракция — фундаментальное понятие.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Без абстракции не будет полиморфизма&lt;/li&gt;
&lt;li&gt;Без полиморфизма не будет Dependency Injection (Внедрение зависимостей)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #essential #oop&lt;/p&gt;</content:encoded></item><item><title>🚀 React — Compound Components</title><link>https://cherkashin.dev/posts/166/</link><guid isPermaLink="true">https://cherkashin.dev/posts/166/</guid><description>🚀 React — Compound Components

Как-то я уже упоминал паттерн Compound Components (Составные компоненты) для React, теперь остановимся на нём немного подробнее.

ℹ️ Compound components — это подход позволяет объединить несколько компонентов в единую сущность, которая неявно имеет общее состояние. Эти компоненты тесно в...</description><pubDate>Mon, 12 Feb 2024 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;🚀 React — Compound Components&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Как-то я &lt;a href=&quot;https://t.me/cherkashindev/67&quot;&gt;уже упоминал&lt;/a&gt; паттерн Compound Components (Составные компоненты) для React, тепе&lt;strong&gt;рь остановимся на н&lt;/strong&gt;ём немного подробнее.&lt;/p&gt;
&lt;p&gt;ℹ️ Compound components — это подход позволяет объединить несколько компонентов в единую сущность, которая неявно имеет общее состояние. Эти компоненты тесно взаимодействуют друг с другом и работают как единое целое, представляя собой полноценный UI компонент.&lt;/p&gt;
&lt;p&gt;🔍 Основные характеристики:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Используется React контекст, чтобы управлять состоянием&lt;/li&gt;
&lt;li&gt;Должен быть главный компонент, в котором хранится состояние и объявляется React контекст&lt;/li&gt;
&lt;li&gt;Все дочерние компоненты используют состояние через React контекст&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ℹ️ Он состоит из 2 простых подходов React:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Композиция компонентов&lt;/li&gt;
&lt;li&gt;Паттерн “&lt;strong&gt;Провайдер” — использование контекста React
**
📝 Вн&lt;/strong&gt;ачале рассмотрим подх**оды по отдельности&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1️⃣ Что такое композиция?&lt;/p&gt;
&lt;p&gt;Вместо вот этого&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;Tile count&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{money} title&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Стоимость&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; icon&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;{&amp;#x3C;MoneyIcon/&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Мы пишем вот так&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;xml&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;xml&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Tile&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Title&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;{title}&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Title&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;{count}&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Icon&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;{icon}&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Icon&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Tile&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Когда это может понадобиться? Например, когда у нас креативный дизайнер и нам нужно угодить ему:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В одном месте, показывать карточку без иконки&lt;/li&gt;
&lt;li&gt;В другом, показывать карточку, где цифра то посередине, то слева, то справа, то на луне&lt;/li&gt;
&lt;li&gt;В третьем, нам нужно добавить иконку, чтобы при наведении показывалось описание&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В итоге, мы можем легко модифицировать любую часть компонента, и по-разному их комбиниров&lt;strong&gt;а&lt;/strong&gt;ть.**&lt;/p&gt;
&lt;p&gt;2️⃣ Паттерн “Провайде**р”&lt;/p&gt;
&lt;p&gt;Здесь идёт речь об обычном использовании контекста реакта, чтобы передавать какие-то данные на любую глубину дерева компонентов, минуя дочерние компоненты.&lt;/p&gt;
&lt;p&gt;🔄 Если объединить два этих подхода, то сможем реали&lt;strong&gt;зовать паттерн Comp&lt;/strong&gt;ound Components. Как пример, можно использовать &lt;a href=&quot;https://mui.com/material-ui/react-tabs/#experimental-api&quot;&gt;компонент табов из библиотеки material-ui&lt;/a&gt;.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; MyTabs&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;   &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabContext&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;       &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabList&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; onChange&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;={&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;handleChange&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;         &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Tab&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; label&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Item One&quot;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;         &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Tab&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; label&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Item Two&quot;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;         &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;Tab&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; label&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Item Three&quot;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;3&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;       &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabList&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Ï&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;     &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabPanel&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Item One&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabPanel&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;     &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabPanel&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Item Two&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabPanel&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;     &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabPanel&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;3&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Item Three&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabPanel&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;   &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;TabContext&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;TabContext — главный компонент, в котором хранится состояние и объявляется React контекст&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Tab&lt;/code&gt;  и &lt;code&gt;TabPanel&lt;/code&gt;  получают текущее значение активного таба неявно через React контекст. Явно значение не передаётся в каждый компонент.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onChange&lt;/code&gt;  объявлен только на компоненте &lt;code&gt;TabList&lt;/code&gt;, компоненты &lt;code&gt;Tab&lt;/code&gt;  неявно получают его из контекста.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4BByJUk5x7M&amp;#x26;ab_channel=HolyJS&quot;&gt;Александр Дунай (Альфа-Банк) — Улучшаем качество кода React-приложения с помощью Compound Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javascriptpatterns.vercel.app/patterns/react-patterns/provider-pattern&quot;&gt;JavaScript Patterns — Provider Patter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javascriptpatterns.vercel.app/patterns/react-patterns/compound-pattern&quot;&gt;JavaScript Pattern — Compound Pattern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#react #frontend #architecture #patterns&lt;/p&gt;</content:encoded></item><item><title>Сегодня увидел, что Хабр советует прочитать мою старую статью с советами о выгорании, поэтому я…</title><link>https://cherkashin.dev/posts/165/</link><guid isPermaLink="true">https://cherkashin.dev/posts/165/</guid><description>Сегодня увидел, что Хабр советует прочитать мою старую статью с советами о выгорании, поэтому я решил напомнить о ней. Как раз подходит, чтобы отвлечься от работы, расслабиться и почитать вечером в пятницу.

https://habr.com/ru/post/598517/

#fridayreading #burnout</description><pubDate>Fri, 02 Feb 2024 15:21:23 GMT</pubDate><content:encoded>&lt;p&gt;Сегодня увидел, что Хабр советует прочитать мою старую статью с советами о выгорании, поэтому я решил напомнить о ней. Как раз подходит, чтобы отвлечься от работы, расслабиться и почитать вечером в пятницу.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/598517/&quot;&gt;https://habr.com/ru/post/598517/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #burnout&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-165-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-165-1.jpg"/></item><item><title>Явное управление ресурсами в TypeScript — using</title><link>https://cherkashin.dev/posts/164/</link><guid isPermaLink="true">https://cherkashin.dev/posts/164/</guid><description>Явное управление ресурсами в TypeScript[ — using

Недавно,](https://t.me/cherkashindev/160) когда я рассказывал, как мы пишем тесты, я уже упоминал, что в TypeScript’е появилось новое ключевое слово using. Оно позволяет нам сделать код чище и более линейным, избавившись от try/finally.

Но мы можем использовать using н...</description><pubDate>Mon, 29 Jan 2024 10:00:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Явное управление ресурсами в TypeScript&lt;/strong&gt;[** — using**&lt;/p&gt;
&lt;p&gt;Недавно,](&lt;a href=&quot;https://t.me/cherkashindev/160&quot;&gt;https://t.me/cherkashindev/160&lt;/a&gt;) когда я рассказывал, как мы пишем тесты, я уже упоминал, что в Type&lt;code&gt;Scrip&lt;/code&gt;t’е появилось новое ключевое слово using. Оно позволяет нам сделать ко&lt;code&gt;д чище и бо&lt;/code&gt;лее линейным, избавившись от &lt;code&gt;try/f&lt;/code&gt;inally.&lt;/p&gt;
&lt;p&gt;Но мы можем использовать using не только, когда открываем файл или подключение к базе данных, иначе его использование ограничилось бы исключительно&lt;code&gt; серв&lt;/code&gt;ером.&lt;/p&gt;
&lt;p&gt;Мне нравится рассматривать using, как Undo/Redo только наоборот, сперва мы выполняем какое-то действие, а в конце отменяем его:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;создали объект, удалили&lt;/li&gt;
&lt;li&gt;показали спиннер и скрыли, когда получили данные&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Причем отмена удобно происходит в самом&lt;code&gt; конце функ&lt;/code&gt;ции, даже если мы используем async/await.&lt;/p&gt;
&lt;p&gt;Вот&lt;code&gt; прос&lt;/code&gt;той пример, как можно использовать using, чтобы показывать/скрывать спиннер в React коде.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// обычный код на React&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;  useEffect&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    (&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      try&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;        setIsLoading&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;        await&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;promise.resolve&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;finally&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;        setIsLoading&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    })()&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }, [])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// такой же код, с использованием using&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;  useEffect&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    (&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      using&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; manager&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; LoadingManager&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(setIsLoading);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;      await&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;promise.resolve&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    })();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;   }, []);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt; * Класс, который управляет состоянием спиннера&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; LoadingManager&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; setIsLoading&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; any&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;setIsLoading&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;constructor&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  [Symbol.dispose]() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;setIsLoading&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;disposer&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// В консоли будет выведено в следующем порядке&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// constructor&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// promise.resolve&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// disposer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play?#code/PTAEAEBcGcFoFMAeAHeBjSCBOWD2XRpIBDAc3lAGYAoAZQE8BbAI1wBsA6AEwEtplc0CgH5hAXlAMW7ABQByXv0Hw5ASmrU0bYtGigAMrmK8AdqQCyxE2XgEA3tVCg0uE0SwBXDPhnIsPADdiSAohSABJaENjHjMALlAZILYPeATWdngrVVAxAD5QK3ochycnSAALPg4wyOjTUhlIT3hVAG5HMpc3TI42XEaAIm73L0h8QfbOgF8NJwBtKVZORQEhAF0ZEs7yquga+AioowaZADNiNiEpsudXaF7+odXlLEmZ6lnqHXoTNFAzh4-pAeK4AUC0FtQKUyh5oLFSKBGFYbAQJCZ4AB3AwnBGWazkLAyJKXVI5fLQ4AAKipoEAQiCAYRA6aBACwggFYQQDcIIAGEDZgB4QQiHOq4swklKtUBU4DTG5lYiY4g8SCgAAKeEYfHgHCw8AebAC8C2HEq8BMxPJBRGjwGMkGflw6qEWp17H1kymX0Bfy21CAA&quot;&gt;Код можно открыть в песочнице&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;К сожалению, нельзя опустить переменную &lt;code&gt;manager&lt;/code&gt;, но это лучше, чем лепить везде &lt;code&gt;try / finally&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management&quot;&gt;using Declarations and Explicit Resource Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://iliazeus.github.io/articles/js-explicit-resource-management-ru/&quot;&gt;Явное управление ресурсами: пробуем новую фичу JavaScript и TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#typescript #frontend&lt;/p&gt;</content:encoded></item><item><title>🍎 Ещё раз об интеграции Notion и Apple Shortcuts</title><link>https://cherkashin.dev/posts/163/</link><guid isPermaLink="true">https://cherkashin.dev/posts/163/</guid><description>🍎 Ещё раз об интеграции Notion и Apple Shortcuts

Пару лет назад я рассказывал, как можно использовать Apple Shortcuts, чтобы настроить быстрое добавление записей в инбокс. А в прошлом году поделился шаблоном, где для использования достаточно вставить токен notion и идентификатор базы. Но вчера я заметил, что теперь д...</description><pubDate>Thu, 25 Jan 2024 10:01:59 GMT</pubDate><content:encoded>&lt;p&gt;🍎 &lt;strong&gt;Ещё раз об интеграции Notion и Apple Shortcuts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Пару лет назад я рассказывал, как можно использовать &lt;a href=&quot;https://t.me/cherkashindev/43&quot;&gt;Apple Shortcuts&lt;/a&gt;, чтобы настроить быстрое добавление записей в инбокс. А в прошлом году &lt;a href=&quot;https://t.me/cherkashindev/103&quot;&gt;поделился шаблоном&lt;/a&gt;, где для использования достаточно вставить токен notion и идентификатор базы. Но вчера я заметил, что теперь даже этого делать не нужно.&lt;/p&gt;
&lt;p&gt;Наконец-то, Notion добавил готовые экшины для добавления записей в Inbox, всё настраивается за минуту.  Жаль, что новый способ работает только на телефоне, приложение Notion для Mac не поддерживает эти действия.&lt;/p&gt;
&lt;p&gt;#notion #automation&lt;/p&gt;</content:encoded></item><item><title>​​Прошлой весной, я наконец-то зарегистрировался на GetMentor, и теперь время от времени мне…</title><link>https://cherkashin.dev/posts/162/</link><guid isPermaLink="true">https://cherkashin.dev/posts/162/</guid><description>​​Прошлой весной, я наконец-то зарегистрировался на GetMentor, и теперь время от времени мне поступают различные вопросы. Некоторые из них решил публиковать здесь на канале.

Вопрос: если для параметра указать тип React.DragEvent&lt;HTMLDivElement&gt; ,то в коде e.target.style.background = &apos;white’ TypeScript ругается, что вп...</description><pubDate>Tue, 23 Jan 2024 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/7ef0375e973b74cf3b483.jpg&quot;&gt;​​&lt;/a&gt;Прошлой весной, я наконец-то зарегистрировался на &lt;a href=&quot;https://getmentor.dev/mentor/cherkashin-aleksandr-1627&quot;&gt;GetMentor&lt;/a&gt;, и теперь время от времени мне поступают различные вопросы. Некоторые из них решил публиковать здесь на кана**ле.&lt;/p&gt;
&lt;p&gt;В**опрос: если для параметра указат&lt;code&gt;ь тип React.DragEvent&amp;#x3C;HTMLDivEl&lt;/code&gt;ement&gt; ,то в&lt;code&gt; коде e.target.style.background = &apos;&lt;/code&gt;white’ TypeScript ругается, что в&lt;code&gt;поле&lt;/code&gt;target отсутствует сво&lt;code&gt;йство&lt;/code&gt; style, почему **так?&lt;/p&gt;
&lt;p&gt;**Ответ:&lt;/p&gt;
&lt;p&gt;Тут всё дело &lt;code&gt;в том &lt;/code&gt;target — элемент, на котором произошло событие (оно могло всплыть к текущему элементу от дочернего). Из-за этого заранее тип target’а не известен, поэтому его нужно привести к нужному типу. Например, вот так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;typescript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(e.target &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; HTMLElement&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;).style.background &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;white&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Вмес&lt;code&gt;то tar&lt;/code&gt;get можно использовать по&lt;code&gt;ле currentTar&lt;/code&gt;get, тип этого поля всегда известен, потому ч&lt;code&gt;то currentTar&lt;/code&gt;get всегда ссылается на текущий элемент, к которому прикреплён обработчик событий. В этом случае можно избежать приведения типа.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;javascript&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;e.currentTarget.style.background &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;white&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://doka.guide/js/event/#pavel-mineev-sovetuet&quot;&gt;Хорошее демо о `target` и `currentTarget` есть в доке&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/js/event/&quot;&gt;Объект события Event&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/js/events/&quot;&gt;Событийная модель&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#question #frontend&lt;/p&gt;</content:encoded></item><item><title>​​⏰Напоминания в Notion</title><link>https://cherkashin.dev/posts/161/</link><guid isPermaLink="true">https://cherkashin.dev/posts/161/</guid><description>​​⏰Напоминания в Notion

Сегодня немного о том, как я облажался, но не сильно. Обычно я оплачиваю подписку иви сразу за год — так дешевле, всего 2000р (≈170 руб / месяц). Но как только подписка заканчивается — списывается оплата за 1 месяц — 399р, что гораздо больше чем 170р.

Что можно сделать, чтобы не забыть оплатит...</description><pubDate>Mon, 22 Jan 2024 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/820419584b93785ac5303.jpg&quot;&gt;​​&lt;/a&gt;&lt;a href=&quot;https://telegra.ph/file/820419584b93785ac5303.jpg&quot;&gt;&lt;strong&gt;⏰Напоминания&lt;/strong&gt;&lt;/a&gt;** в Notion**&lt;/p&gt;
&lt;p&gt;Сегодня немного о том, как я облажался, но не сильно. Обычно я оплачиваю подписку иви сразу за год — так дешевле, всего 2000р (≈170 руб / месяц). Но как только подписка заканчивается — списывается оплата за 1 месяц — 399р, что гораздо больше чем 170р.&lt;/p&gt;
&lt;p&gt;Что можно сделать, чтобы не забыть оплатить подписку (отключить авто продление!)?&lt;/p&gt;
&lt;p&gt;Если вы, как и я, ведёте свои задачи и проекты в Notion, то у вас скорее всего есть таблица, где отображаются задачи, которые вы должны выполнить сегодня. В таком случае вы можете:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Создать задачу в Notion&lt;/li&gt;
&lt;li&gt;Указать дату выполнения, немного раньше завершения подписки&lt;/li&gt;
&lt;li&gt;В указанную дату задача появится в вашем списке на сегодня&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Например, моя подписка заканчивается 8 января 2025 года, поэтому я поставлю дату 27 декабря 2024 года, чтобы позаботиться об это заранее.&lt;/p&gt;
&lt;p&gt;Я уже описывал этот способ в статье &lt;a href=&quot;https://habr.com/ru/articles/696698/&quot;&gt;Система личного планирования в Notion. Эпизод 2 — Управление проектами.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#notion&lt;/p&gt;</content:encoded></item><item><title>🧹 Тестирование — подчищаем за собой</title><link>https://cherkashin.dev/posts/160/</link><guid isPermaLink="true">https://cherkashin.dev/posts/160/</guid><description>🧹 Тестирование — подчищаем за собой

Так исторически сложилось, что у нас на проекте нет юнит тестов, только интеграционные и e2e.

Иногда  в тестах приходится подчищать за собой — удалять созданные во время выполнения теста объекты в базе, чтобы не влиять на результат других тестов. Это конечно, лишь ухудшает читабел...</description><pubDate>Thu, 18 Jan 2024 07:23:33 GMT</pubDate><content:encoded>&lt;p&gt;**🧹 Тестирование — подчищаем за собой **&lt;/p&gt;
&lt;p&gt;Так исторически сложилось, что у нас на проекте нет юнит тестов, только интеграционные и e2e.&lt;/p&gt;
&lt;p&gt;Иногда  в тестах приходится подчищать за собой — удалять созданные во время выполнения теста объекты в базе, чтобы не влиять на результат других тестов. Это конечно, лишь ухудшает читабельность кода.&lt;/p&gt;
&lt;p&gt;Мы прошли некоторую эволюцию подходов для создания и удаления объектов:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Мы использовали &lt;code&gt;try/finally&lt;/code&gt; , где все созданные объекты удаляются внутри блока finally. Выглядит сомнительно, когда нужно городить подобную конструкцию во многих тестах.&lt;/li&gt;
&lt;li&gt;Перешли к использованию функций с колбэками. Утилитная функция создаёт и удаляет объект, а мы передаём лишь колбэк, в котором описываем логику теста и нужные нам проверки.&lt;/li&gt;
&lt;li&gt;Внедрили &lt;code&gt;IDisposable&lt;/code&gt; классы, которые мы называем Creator’ами. Они делают то же самое, что и функции с колбэками, но не добавляют ненужную вложенность, что улучшает читаемость кода. Они чем-то напоминают &lt;a href=&quot;https://www.notion.so/9547317d39b140a181c2eaff49b03d0b?pvs=21&quot;&gt;PageObjectModel&lt;/a&gt; в e2e тестах.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Использование паттерна с классами &lt;code&gt;IDisposable&lt;/code&gt; также подходит для активации определенной настройки только в рамках одного теста и отключения её по завершении теста.&lt;/p&gt;
&lt;p&gt;Такой подход не ограничивается только лишь C# — в &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management&quot;&gt;TypeScript 5.2&lt;/a&gt;. уже появилась поддержка &lt;code&gt;using&lt;/code&gt; и, возможно, скоро она появится и в &lt;a href=&quot;https://github.com/tc39/proposal-explicit-resource-management&quot;&gt;JavaScript&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#csharp #javascript #typescript #tests&lt;/p&gt;</content:encoded></item><item><title>🗓 Cron теперь Notion Calendar</title><link>https://cherkashin.dev/posts/159/</link><guid isPermaLink="true">https://cherkashin.dev/posts/159/</guid><description>🗓 Cron теперь Notion Calendar

Некоторое время назад Notion купил Cron, и вот недавно состоялся релиз, теперь Cron - это Notion календарь, в котором доступна интеграция, как с гугл календарём, так и с базами в Notion.

Базы отображаются в левом нижнем углу, а записи - в верхней части календаря.

https://calendar.notio...</description><pubDate>Tue, 16 Jan 2024 07:29:57 GMT</pubDate><content:encoded>&lt;p&gt;🗓** Cron теперь Notion Calendar**&lt;/p&gt;
&lt;p&gt;Некоторое время назад Notion купил &lt;a href=&quot;https://cron.com/&quot;&gt;Cron&lt;/a&gt;, и вот недавно состоялся релиз, теперь Cron - это Notion календарь, в котором доступна интеграция, как с гугл календарём, так и с базами в Notion.&lt;/p&gt;
&lt;p&gt;Базы отображаются в левом нижнем углу, а записи - в верхней части календаря.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://calendar.notion.so&quot;&gt;https://calendar.notion.so&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#notion&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-159-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-159-1.jpg"/></item><item><title>Пару месяцев назад я упоминал codeium — бесплатную альтернативу копайлоту. На новогодних праздниках…</title><link>https://cherkashin.dev/posts/153/</link><guid isPermaLink="true">https://cherkashin.dev/posts/153/</guid><description>Пару месяцев назад я упоминал codeium — бесплатную альтернативу копайлоту. На новогодних праздниках наконец-то попробовал его на своём пет-проекте, и довольно часто он действительно ускоряет разработку. На скриншотах можно увидеть как codeium:

Выводит значение enum’аПомогает писать тернарникиГенерирует код по запросу ...</description><pubDate>Mon, 15 Jan 2024 10:00:08 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev/143&quot;&gt;Пару месяцев назад я упоминал codeium&lt;/a&gt; — бесплатную альтернативу копайлоту. На новогодних праздниках наконец-то попробовал его на своём пет-проекте, и довольно часто он действительно ускоряет разработку. На скриншотах можно увидеть как codeium:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Выводит значение enum’а&lt;/li&gt;
&lt;li&gt;Помогает писать тернарники&lt;/li&gt;
&lt;li&gt;Генерирует код по запросу в чате&lt;/li&gt;
&lt;li&gt;Может сгенерировать JSDoc или объяснить код&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В текущих реалиях нужно включать VPN, чтобы работать с ChatGPT из России, здесь же есть встроенный чат, который работает без VPN 👍.&lt;/p&gt;
&lt;p&gt;#ai&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-154-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-154-1.jpg"/></item><item><title>📖 Михаил Горбачёв: В меняющемся мире</title><link>https://cherkashin.dev/posts/152/</link><guid isPermaLink="true">https://cherkashin.dev/posts/152/</guid><description>📖 Михаил Горбачёв: В меняющемся мире

На новогодних удалось не только пить, есть, спать и сбить режим, но и немного почитать. Перед новым годом спонтанно зашёл в Читай Город и купил книгу “Михаил Горбачёв: В меняющемся мире”, очень интересная и читается на одном дыхании.

📚 Книга проливает свет на ключевые моменты ис...</description><pubDate>Fri, 12 Jan 2024 10:00:05 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;a href=&quot;https://www.labirint.ru/books/660596/&quot;&gt;Михаил Горбачёв: В меняющемся мире&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;На новогодних удалось не только пить, есть, спать и сбить режим, но и немного почитать. Перед новым годом спонтанно зашёл в Читай Город и купил книгу “Михаил Горбачёв: В меняющемся мире”, очень интересная и читается на одном дыхании.&lt;/p&gt;
&lt;p&gt;📚 Книга проливает свет на ключевые моменты истории СССР в период перестройки под руководством Михаила Горбачёва. Название отражает содержание, фокусируясь в основном на событиях, формировавших жизнь Горбачёва&lt;/p&gt;
&lt;p&gt;💭 Уделяется внимание новому мышлению, которому следовала советская власть в период перестройки&lt;/p&gt;
&lt;p&gt;💣 Особое внимание уделяется тому, каким образом останавливалась гонка вооружений и как завершилась холодная война, раскрывая усилия советского руководства, положившие конец этому периоду&lt;/p&gt;
&lt;p&gt;🌐  Рассматривается оттепель в отношениях СССР и США при Горбачёве и Рейгане&lt;/p&gt;
&lt;p&gt;🔗 В книге Горбачёв рассказывает, почему было важно сохранить СССР, и к каким проблемам мог привести его развал (и в итоге привёл). Естественно описывается как он в итоге распался.&lt;/p&gt;
&lt;p&gt;#book #politics&lt;/p&gt;</content:encoded></item><item><title>☃️ Итоги 2023 года</title><link>https://cherkashin.dev/posts/151/</link><guid isPermaLink="true">https://cherkashin.dev/posts/151/</guid><description>☃️ Итоги 2023 года

2023 год был достаточно насыщенным, и наверно стоит немного оглянуться назад и подвести итоги: что удалось сделать, а над чем ещё нужно поработать. Ведь иначе может показаться, что за год ничего не было сделано.

🏃 Пробежал полумарафон

🎾 Начал играть в большой теннис  

🧳 Поездил по России и пос...</description><pubDate>Sat, 30 Dec 2023 14:38:45 GMT</pubDate><content:encoded>&lt;p&gt;☃️** Итоги 2023 года**&lt;/p&gt;
&lt;p&gt;2023 год был достаточно насыщенным, и наверно стоит немного оглянуться назад и подвести итоги: что удалось сделать, а над чем ещё нужно поработать. Ведь иначе может показаться, что за год ничего не было сделано.&lt;/p&gt;
&lt;p&gt;🏃 &lt;a href=&quot;https://t.me/cherkashindev/100&quot;&gt;Пробежал полумарафон&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;🎾 Начал играть в большой теннис  &lt;/p&gt;
&lt;p&gt;🧳 Поездил по России и посетил 5 стран&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;🇷🇺 Москва, Краснодар, Тюмень, Екатеринбург 
🇧🇾 Минск
🇦🇲 Ереван
🇬🇪 Тбилиси
🇦🇿 Баку
🇹🇷 Стамбул, Каппадокия, Сиде
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;🌑 Сыграл в пейнтбол&lt;/p&gt;
&lt;p&gt;✈️ 74 публикации в телеграмм канале&lt;/p&gt;
&lt;p&gt;📝 6 статей на Хабре и VC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/725460/&quot;&gt;Интегрируем Яндекс Музыку в Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/729980/&quot;&gt;Свифт умирает или как получать валютные платежи в 2023 году&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/754248/&quot;&gt;Бессильный сборщик мусора или неуправляемая память в .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vc.ru/services/599329-kak-platforma-upravleniya-znaniyami-uproshchaet-onbording-teamly&quot;&gt;Как платформа управления знаниями упрощает онбординг — TEAMLY&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/779492/&quot;&gt;Как автоматизировать использование дизайн токенов с помощью Stylelint и PostCSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/779524/&quot;&gt;Как я документацию для дизайн-токенов в Storybook генерировал&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🧑‍💻 Довёл до ума &lt;a href=&quot;https://github.com/acherkashin/yandex-music-extension&quot;&gt;VS Code расширение&lt;/a&gt; и &lt;a href=&quot;https://github.com/acherkashin/yandex-music-open-api&quot;&gt;Open API документацию&lt;/a&gt; для Яндекс Музыки&lt;/p&gt;
&lt;p&gt;🧑‍💻 Поконтрибьютил в &lt;a href=&quot;https://github.com/UX-and-I/storybook-design-token&quot;&gt;Storybook Design Token&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;📚 Прошёл пару курсов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/145&quot;&gt;Старт на Хабре&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://practicum.yandex.ru/algorithms-interview/&quot;&gt;Подготовка к алгоритмическому собеседованию&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📖 Читал не много&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/78&quot;&gt;Проект “Феникс”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.litres.ru/book/ichiro-kishimi/smelost-ne-nravitsya-kak-polubit-sebya-nayti-svoe-prizvanie-40736615/&quot;&gt;Смелость не нравиться. Как полюбить себя, найти свое призвание и выбрать счастье&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.litres.ru/book/mark-goulston/ne-meshay-sebe-zhit-kak-spravitsya-so-strahom-obidoy-chuvstv-56563513/&quot;&gt;Не мешай себе жить&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/149&quot;&gt;Скорбь сатаны — Мария Корелли&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🧑‍🏫 &lt;a href=&quot;https://getmentor.dev/mentor/cherkashin-aleksandr-1627&quot;&gt;Зарегистрировался на GetMentor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;❌ Конечно, планов было гораздо больше и не всё удалось сделать.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Не успел подготовиться к собеседованию в Яндекс. Поэтому не пошёл на второе этап.&lt;/li&gt;
&lt;li&gt;Не успел довести до ума утилиту для анализа Code Review&lt;/li&gt;
&lt;li&gt;Не нашёл времени на английский&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/144&quot;&gt;Осталось множество незаконченных проектов&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Надеюсь следующий год будет по крайней мере не хуже.&lt;/p&gt;
&lt;p&gt;Всех с наступающим новым годом! 🎉 🎄❄️☃️🌨️&lt;/p&gt;
&lt;p&gt;#итогигода&lt;/p&gt;</content:encoded></item><item><title>📖 Хабр. Технотекст 2023</title><link>https://cherkashin.dev/posts/150/</link><guid isPermaLink="true">https://cherkashin.dev/posts/150/</guid><description>📖 Хабр. Технотекст 2023

Ежегодно Хабр проводит конкурс статей Технотекст, где каждый может принять участие, чтобы заслужить почёт и славу (или же нет).

Если вы хотите прочитать пару-тройку интересных статей, то можете найти для себя много интересного в прошлогоднем шортлисте технотекста. Некоторые статьи из этого сп...</description><pubDate>Thu, 28 Dec 2023 10:00:06 GMT</pubDate><content:encoded>&lt;p&gt;**📖 Хабр. Технотекст 2023
**
Ежегодно Хабр проводит конкурс статей &lt;a href=&quot;https://habr.com/ru/companies/habr/articles/773724/&quot;&gt;Технотекст&lt;/a&gt;, где каждый может принять участие, чтобы заслужить почёт и славу (или же нет).&lt;/p&gt;
&lt;p&gt;Если вы хотите прочитать пару-тройку интересных статей, то можете найти для себя много интересного в &lt;a href=&quot;https://habr.com/ru/companies/habr/articles/715670/&quot;&gt;прошлогоднем шортлисте технотекста&lt;/a&gt;. Некоторые статьи из этого списка я уже рекомендовал ранее:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/88&quot;&gt;Не трогайте разработчиков. Отстаньте. Просто не беспокойте&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/cherkashindev/95&quot;&gt;Процесс ревью кода структурно порочен. Вот, как его исправить&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В прошлом году я участвовал со статьями о Notion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/696416/&quot;&gt;Система личного планирования в Notion. Эпизод 1 — Инбокс&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/696698/&quot;&gt;Система личного планирования в Notion. Эпизод 2 — Управление проектами&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А в этом году снова решил поучаствовать со статьёй &lt;a href=&quot;https://habr.com/ru/articles/725460/&quot;&gt;Интегрируем Яндекс Музыку в Visual Studio Code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Надеюсь, что в этом году фортуна улыбнётся мне 🤞.&lt;/p&gt;
&lt;p&gt;#habr&lt;/p&gt;</content:encoded></item><item><title>📖 Скорбь сатаны — Мария Корелли</title><link>https://cherkashin.dev/posts/149/</link><guid isPermaLink="true">https://cherkashin.dev/posts/149/</guid><description>📖 Скорбь сатаны — Мария Корелли

Сегодня пора отвлечься от кода и дать мозгу небольшой отдых — новый год уже близко! Можно немного отодвинуть ноут в сторону (но не слишком далеко) и расслабиться. На выходных дочитал “Скорбь сатаны” Марии Корелли.

Это одна из тех книг, от которых невозможно оторваться. Завораживающая ...</description><pubDate>Fri, 22 Dec 2023 10:00:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;📖 Скорбь сатаны — Мария Корелли&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня пора отвлечься от кода и дать мозгу небольшой отдых — новый год уже близко! Можно немного отодвинуть ноут в сторону (но не слишком далеко) и расслабиться. На выходных дочитал “Скорбь сатаны” Марии Корелли.&lt;/p&gt;
&lt;p&gt;Это одна из тех книг, от которых невозможно оторваться. &lt;strong&gt;Завораживающая история, которая рассказывает, что за деньги настоящее счастье не купишь.&lt;/strong&gt; Очень рекомендую 👍.&lt;/p&gt;
&lt;p&gt;Со временем всё забывается, поэтому пока свежи впечатления, решил поделиться некоторыми цитатами из книги:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Как правило - богачи самые несчастные люди на свете.&lt;/li&gt;
&lt;li&gt;Я устал от самого себя. И Мне никогда не удается отдохнуть.&lt;/li&gt;
&lt;li&gt;Настоящее - самое приемлемое время.&lt;/li&gt;
&lt;li&gt;Дни — белые странницы божественной хроники человеческой жизни.&lt;/li&gt;
&lt;li&gt;Я смотрю на бесконечное будущее, на которое я обречен, скорее с ужасом, чем с благодарностью, так как я зря растратил свое время и упустил бесценные возможности.&lt;/li&gt;
&lt;li&gt;Как странно писать о себе в прошедшем времени, как о том, кто уже не имеет отношения к настоящему.&lt;/li&gt;
&lt;li&gt;Никогда ни на что не следует смотреть слишком мрачно.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Буду благодарен, если посоветуете, что можно почитать на новогодних праздниках 📚🙏&lt;/p&gt;
&lt;p&gt;#book #fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​Если вы ещё не забыли, в предыдущем посте я упомянул, что прошёл мини-курс по написанию статей на…</title><link>https://cherkashin.dev/posts/148/</link><guid isPermaLink="true">https://cherkashin.dev/posts/148/</guid><description>​​Если вы ещё не забыли, в предыдущем посте я упомянул, что прошёл мини-курс по написанию статей на Хабр.
А сегодня хочу поделиться статьями, которые написал за время обучения:

1️⃣ Как автоматизировать использование дизайн токенов с помощью Stylelint и PostCSS

2️⃣ Как я документацию для дизайн-токенов в Storybook ген...</description><pubDate>Tue, 19 Dec 2023 10:00:06 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/d928bc00b5c7d9386293d.jpg&quot;&gt;​​&lt;/a&gt;Если вы ещё не забыли, в &lt;a href=&quot;https://t.me/cherkashindev/145&quot;&gt;предыдущем посте&lt;/a&gt; я упомянул, что прошёл мини-курс по написанию статей на Хабр.
А сегодня хочу поделиться статьями, которые написал за время обучения:&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;a href=&quot;https://habr.com/ru/articles/779492/&quot;&gt;Как автоматизировать использование дизайн токенов с помощью Stylelint и PostCSS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2️⃣ &lt;a href=&quot;https://habr.com/ru/articles/779524/&quot;&gt;Как я документацию для дизайн-токенов в Storybook генерировал&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#frontend #design #automation #storybook&lt;/p&gt;</content:encoded></item><item><title>Как я документацию для дизайн-токенов в Storybook генерировал</title><link>https://cherkashin.dev/articles/design-tokens-in-storybook/</link><guid isPermaLink="true">https://cherkashin.dev/articles/design-tokens-in-storybook/</guid><description>Я думаю ни для кого не секрет, что бизнес процессы в стартапах, мягко сказать,  хромают. Я же как оптимист вижу возможность в каждой трудности, поэтому всегда считал, что это отличная возможность проявить инициативу и попробовать что-то автоматизировать или улучшить процессы команды (ну или хотя бы попробовать).
Сегодня хочу рассказать, как можно легко реализовать документацию для дизайн-токенов в Storybook, и заодно поделиться тем, как и почему я пытался это сделать, и что из этого вышло. Статья будет полезна для разработчиков, которые уже используют дизайн токены и ищут лёгкий способ их документации.</description><pubDate>Mon, 18 Dec 2023 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/design-tokens-in-storybook/tipical-situation.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/design-tokens-in-storybook/tipical-situation.png"/></item><item><title>📺 Дизайн токены</title><link>https://cherkashin.dev/posts/147/</link><guid isPermaLink="true">https://cherkashin.dev/posts/147/</guid><description>📺 Дизайн токены

Сегодня я порекомендую несколько докладов о дизайн токенах

1️⃣ MoscowJS 49 — Дизайн-система на фронтенде — Сергей Володин

Сергей рассказывает, как первый редизайн почты и других продуктов mail.ru — “где нужно было поменять только цвет” занял неделю и в нём участвовали 10 человек.

В итоге они поняли...</description><pubDate>Fri, 15 Dec 2023 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;📺 Дизайн токены&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня я порекомендую несколько докладов о дизайн токенах&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;a href=&quot;https://www.youtube.com/watch?v=Jn2IgLUIx3Y&amp;#x26;ab_channel=MoscowJS&quot;&gt;MoscowJS 49 — Дизайн-система на фронтенде — Сергей Володин&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Сергей рассказывает, как первый редизайн почты и других продуктов &lt;a href=&quot;http://mail.ru/&quot;&gt;mail.ru&lt;/a&gt; — “где нужно было поменять только цвет” занял неделю и в нём участвовали 10 человек.&lt;/p&gt;
&lt;p&gt;В итоге они поняли, что что-то не так с их архитектурой, и что одного компонентного подхода не достаточно. &lt;a href=&quot;http://mail.ru/&quot;&gt;Mail.ru&lt;/a&gt; — большая компания, и на разных проектах могут быть разные технологии. Но помимо этого, ещё определённо будут разные платформы — не только веб, но и, например, мобилки. В таком случае у вас физически нет возможности заставить использовать всех одну и туже библиотеку компонентов.&lt;/p&gt;
&lt;p&gt;Чтобы ускорить разработку, в проекте должна использоваться дизайн-система. Дизайн-система — язык, на котором описываются интерфейсы. Это не просто UI Kit, дизайн-система описывает как работать со шрифтами, как правильно компоновать компоненты, описывает анимации и прочее. К тому же, дизайн-система должна быть платформо-независимой.&lt;/p&gt;
&lt;p&gt;И далее рассматриваются:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Дизайн токены — ядро дизайн системы.&lt;/li&gt;
&lt;li&gt;Проектирование API компонентов. Что интересно, они запретили прокидывать в компоненты className и инлайн стили.&lt;/li&gt;
&lt;li&gt;Как реализовывать темы.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2️⃣ &lt;a href=&quot;https://www.youtube.com/watch?v=X3ciRPwzEMs&amp;#x26;t=8s&amp;#x26;ab_channel=FrontendChannel&quot;&gt;Токены в дизайн-системах / Юрий Ветров (Mail.Ru Group)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Еще один доклад от Mail.Ru. Здесь подробно рассказывается о том, как происходила унификация различных продуктов в компании, почему библиотека компонентов не решила все проблемы и как помогли дизайн-токены.&lt;/p&gt;
&lt;p&gt;3️⃣ &lt;a href=&quot;https://www.youtube.com/watch?v=M0iZg7mlCEE&amp;#x26;ab_channel=Wrike%26WrikersCommunity&quot;&gt;Дизайн-система на токенах в Figma, коде и проде – Константин Подрубный, Wrike&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Тут можно посмотреть демку, как можно редактировать дизайн-токены прямо из фигмы, и как они сразу же уходили в продакшн.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://paradigm.mail.ru/design_tokens/colors&quot;&gt;Дизайн система Paradigm от Mail.ru&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://designsystemsclub.ru/&quot;&gt;КОД — клуб отечественных дизайн систем&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://amzn.github.io/style-dictionary/&quot;&gt;Styledictionary&lt;/a&gt; — инструмент для генерации дизайн токенов под разные платформы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #design #architecture&lt;/p&gt;</content:encoded></item><item><title>Как автоматизировать использование дизайн токенов с помощью Stylelint и PostCSS</title><link>https://cherkashin.dev/articles/automate-design-tokens-usage-with-stylelint-postcss/</link><guid isPermaLink="true">https://cherkashin.dev/articles/automate-design-tokens-usage-with-stylelint-postcss/</guid><description>Сегодня я хотел бы поделиться своим небольшим успехом в автоматизации. В какой-то момент я понял, что во время код ревью я указываю разработчикам на одни и те же ошибки. Но, что ещё хуже, я сам время от времени допускаю эти ошибки. Сегодня хочу рассказать об одной из таких проблем, которую я решил с помощью PostCSS + Stylelint, и о том, как я это сделал.
Статья будет полезна для разработчиков, которые уже используют или собираются использовать дизайн токены.</description><pubDate>Tue, 12 Dec 2023 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/automate-design-tokens-usage-with-stylelint-postcss/image1.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/automate-design-tokens-usage-with-stylelint-postcss/image1.png"/></item><item><title>✍️ Мини-Курс на Хабре</title><link>https://cherkashin.dev/posts/145/</link><guid isPermaLink="true">https://cherkashin.dev/posts/145/</guid><description>✍️ Мини-Курс на Хабре

В ноябре Хабр запускал мини-курс из 4-х занятий по написанию статей и ведению блогов компаний. Моей компании, корпоративный блог не нужен, но статьи время от времени стараюсь писать. Поэтому курс решил пройти и поделиться здесь некоторыми заметками, так сказать, чтобы всё лучше усвоилось.

👆 Фор...</description><pubDate>Mon, 11 Dec 2023 08:01:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;✍️ Мини-Курс на Хабре&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В ноябре Хабр запускал мини-курс из 4-х занятий по написанию статей и ведению блогов компаний. Моей компании, корпоративный блог не нужен, но статьи время от времени стараюсь писать. Поэтому курс решил пройти и поделиться здесь некоторыми заметками, так сказать, чтобы всё лучше усвоилось.&lt;/p&gt;
&lt;p&gt;👆 &lt;strong&gt;Формат статьи&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Перед написанием статьи нужно определиться с её форматом, он повлияет на ход всей статьи, от названия до содержания. Вот 4 основных типа статей и примеры заголовков для них:&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;strong&gt;Кейс&lt;/strong&gt; — “Как я водил слона по лабиринту”
2️⃣ &lt;strong&gt;Туториал/инструкция&lt;/strong&gt;  — “Как водить слонов по лабиринту: не повторяйте наших ошибок, держите за хобот”
3️⃣ &lt;strong&gt;Обзор&lt;/strong&gt; — “Лучшие слоны для лабиринтов или почему мы предпочитаем индийских”
4️⃣ &lt;strong&gt;Аналитика&lt;/strong&gt; — “Самые важные качества у слонов в лабиринтах на нашем опыте”&lt;/p&gt;
&lt;p&gt;💡 &lt;strong&gt;Кейс&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Рассказываете, не что вы делали, а как, и описываете: процессы, ошибки, препятствия. То, как вы что-то делали — менее важно.&lt;/li&gt;
&lt;li&gt;Должно быть больше информации о непосредственном опыте именно вашей команды, а не какой-то абстрактной команды. Поэтому нужно больше деталей о работе вашей команды, о каких-то конкретных ситуациях.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📃 &lt;strong&gt;Туториал/инструкция&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Тут мы описываем конкретные шаги, поэтому конкретизация более важна.&lt;/li&gt;
&lt;li&gt;Детали компании/команды менее важны, но нужен минимальный контекст, чтобы было понятно, что вы знаете, о чём говорите.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🎨 &lt;strong&gt;Оформление&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда мы пишем статью на Хабр, то помимо основного содержимого, нам нужно позаботиться о том, как статья будет выглядеть в ленте. Это нужно, чтобы завлечь читателя её прочесть. Здесь важно обратить внимание на:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Заголовок&lt;/li&gt;
&lt;li&gt;КДПВ — картинка для привлечения внимания&lt;/li&gt;
&lt;li&gt;Лид — вводный абзац&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📰 &lt;strong&gt;Заголовок&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Заголовок не должен вводить в заблуждение, должен отображать суть статьи&lt;/li&gt;
&lt;li&gt;Может состоять из 2-х частей: Игровой (креативный) заголовок + рабочий&lt;/li&gt;
&lt;li&gt;Рабочий заголовок — заголовок, который мы используем, когда пишем статью.&lt;/li&gt;
&lt;li&gt;Если пишем серию статей, то не нужно указывать “Часть 1”, “Часть 2”, …, чтобы не отпугнуть читателей. Лучше сделать каждую статью в серии самодостаточной, чтобы не требовалось читать предыдущие статьи из серии.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📝 &lt;strong&gt;Примеры заголовков&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Рабочий заголовок: Как написать хорошую статью на Хабр&lt;/p&gt;
&lt;p&gt;Игровой + рабочий: Редактируй трезвым: статья о том, как писать хорошие статьи на Хабр&lt;/p&gt;
&lt;p&gt;Короткий: Топовая статья — как?&lt;/p&gt;
&lt;p&gt;🔝 &lt;strong&gt;Вводный абзац (лид)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Тут нужно раскрыть:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;О чём вы хотите рассказать и почему&lt;/li&gt;
&lt;li&gt;Указать целевую аудиторию&lt;/li&gt;
&lt;li&gt;Представиться, так вы будете для них коллегой по цеху, а не каким-то абстрактным чуваком в интернете&lt;/li&gt;
&lt;li&gt;Лид не должен раскрывать все идеи статьи, нужно сохранять интригу, чтобы завлечь открыть саму статью&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✍️ &lt;strong&gt;Основной контент&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Больше конкретики. Например, нужно писать не “наш проект очень старый”, а “мы пережили 2 миграции с Flash на JQuery и с JQuery на Angular”&lt;/li&gt;
&lt;li&gt;Описывать личный опыт и вполне конкретные ситуации/проблемы/провалы и успешные решения.&lt;/li&gt;
&lt;li&gt;Не нужно использовать заумные предложения, мы пишем не для научного издания. Например, можно задать себе вопрос “Сказал бы я так в жизни?”, и если нет, то лучше переформулировать.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#habr&lt;/p&gt;</content:encoded></item><item><title>🚮 Трата времени</title><link>https://cherkashin.dev/posts/144/</link><guid isPermaLink="true">https://cherkashin.dev/posts/144/</guid><description>🚮 Трата времени

Мне кажется больше всего времени мы тратим не на какую то рутину, а на следующие 2 вещи:

начинаем что-то и не доделываем, хотя дело стоящеепродолжаем делать то, что никому не нужно

Прежде чем за что-то браться — стоит подумать, а стоящее ли дело? Если дело стоящее, то получится ли довести его до кон...</description><pubDate>Thu, 07 Dec 2023 08:01:00 GMT</pubDate><content:encoded>&lt;p&gt;🚮 &lt;strong&gt;Трата времени&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Мне кажется больше всего времени мы тратим не на какую то рутину, а на следующие 2 вещи:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;начинаем что-то и не доделываем, хотя дело стоящее&lt;/li&gt;
&lt;li&gt;продолжаем делать то, что никому не нужно&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Прежде чем за что-то браться — стоит подумать, а стоящее ли дело? Если дело стоящее, то получится ли довести его до конца? Возможно, у вас уже куча незаконченных дел и лучше посвятить свободный вечер именно им, а не пополнять этот список ещё одним незаконченным проектом. Лучше просто записать все мысли о новой идее, но не браться за неё прямо сейчас. В противном случае, вы рискуете просто потратить время и получить ещё одно незаконченное дело, которое будет вас преследовать.&lt;/p&gt;
&lt;p&gt;Если взялись за дело и в процессе поняли, что оно лишено всякого смысла — лучше не тратить время впустую. Возможно вы хотите внедрить новую технологию в проект — сперва обсудите это с командой, возможно окажется, что это никому не нужно (а возможно наоборот).&lt;/p&gt;
&lt;p&gt;Как-то будучи студентом, я решил реализовать мобильное приложение для онлайн-кабинета студента нашего универа, убил кучу времени и даже реализовал прототип. Затем, поговорив с начальником отдела разработки, понял, что это никому не нужно, а время уже потрачено. Можно было просто сперва обсудить это, сэкономил бы кучу времени.&lt;/p&gt;
&lt;p&gt;Если говорить о незаконченных делах, то вот так выглядит мой список проектов в Notion. На многие из них я потратил больше недели, но так и не довёл до конца. В этом году всё-таки смог доделать несколько начатых проектов, посмотрим что будет в следующем.&lt;/p&gt;
&lt;p&gt;О том, почему важно доводить проекты до конца, я писал &lt;a href=&quot;https://t.me/cherkashindev/123&quot;&gt;здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#planning #about_me&lt;/p&gt;</content:encoded></item><item><title>Именование юнит тестов</title><link>https://cherkashin.dev/posts/142/</link><guid isPermaLink="true">https://cherkashin.dev/posts/142/</guid><description>Именование юнит тестов

Мне всегда нравятся “информативные” названия тестов вроде “TestLogin”.

Смотришь и из названивая в принципе не понятно, что именно мы тестируем.

В книге “Искусство автономного тестирования (The Art of Unit Testing)” предлагается следующий способ именования тестов:[UnitOfWorkName][ScenarioUnderT...</description><pubDate>Tue, 14 Nov 2023 09:08:40 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Именование юнит тестов&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Мне всегда нравятся “информативные” названия тестов вроде “TestLogin”.&lt;/p&gt;
&lt;p&gt;Смотришь и из названивая в принципе не понятно, что именно мы тестируем.&lt;/p&gt;
&lt;p&gt;В книге &lt;a href=&quot;https://vk.com/wall-54530371_183645&quot;&gt;“Искусство автономного тестирования (The Art of Unit Testing)”&lt;/a&gt; предлагается следующий способ именования тестов:&lt;code&gt;[UnitOfWorkName]_[ScenarioUnderTest]_[ExpectedBehavior]&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UnitOfWorkName — имя тестируемого метода либо группы методов или классов&lt;/li&gt;
&lt;li&gt;Scenario – условия, при которых тестируется автономная единица&lt;/li&gt;
&lt;li&gt;ExpectedBehavior – что должен делать метод при заданных условиях&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Например, если мы тестируем вход пользователя с неверным паролем и ожидаем, что произойдёт ошибка, то названия теста может выглядеть так:&lt;code&gt; TestLogin_InvalidPassword_ThrowsException.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;#csharp #tests&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-142-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-142-1.jpg"/></item><item><title>​​🎨 Дизайн токены</title><link>https://cherkashin.dev/posts/139/</link><guid isPermaLink="true">https://cherkashin.dev/posts/139/</guid><description>​​🎨 Дизайн токены

Дизайн-токен — самое маленькое, атомарное правило дизайн системы:

Какого цвета бордер;Какого размера шрифт заголовка.
По сути — переменная.

Демка состоит из 2 частей:
1️⃣ Автозамена цветов, шрифтов на соотвутствующие переменные с помощью stylelint-declaration-strict-value
2️⃣ Отображение всех этих...</description><pubDate>Mon, 06 Nov 2023 08:01:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/428616d4bd618a7750d40.jpg&quot;&gt;​​&lt;/a&gt;**🎨 Дизайн токены&lt;/p&gt;
&lt;p&gt;**Дизайн-токен — самое маленькое, атомарное правило дизайн системы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Какого цвета бордер;&lt;/li&gt;
&lt;li&gt;Какого размера шрифт заголовка.
По сути — переменная.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Демка состоит из 2 частей:
1️⃣ Автозамена цветов, шрифтов на соотвутствующие переменные с помощью &lt;a href=&quot;https://github.com/AndyOGo/stylelint-declaration-strict-value&quot;&gt;stylelint-declaration-strict-value&lt;/a&gt;
2️⃣ Отображение всех этих переменных в storybook с помощью &lt;a href=&quot;https://github.com/UX-and-I/storybook-design-token&quot;&gt;storybook-design-token&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Позже опишу подробнее, а пока исходники можно посмотреть &lt;a href=&quot;https://github.com/acherkashin/design-tokens-demo&quot;&gt;здесь&lt;/a&gt;, а опубликованный &lt;a href=&quot;https://acherkashin.github.io/design-tokens-demo/&quot;&gt;сторибук здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Для публикации использовал &lt;a href=&quot;https://t.me/cherkashindev/17&quot;&gt;мою старую инструкцию по github pages&lt;/a&gt;, адаптировав её под pnpm:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В pnpm нет **pre **скриптов, поэтому нельзя использовать predeploy&lt;/li&gt;
&lt;li&gt;Добавил &lt;a href=&quot;https://github.com/pnpm/action-setup&quot;&gt;pnpm/action-setup&lt;/a&gt; для установки&lt;/li&gt;
&lt;li&gt;В настройках репозитория “Settings &gt; Actions &gt; General &gt; Workflow permissions” &lt;a href=&quot;https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#configuring-the-default-github_token-permissions&quot;&gt;нужно разрешить доступ&lt;/a&gt; на запись при использовании токена&lt;code&gt;GITHUB_TOKEN&lt;/code&gt;
Код github actions полностью можно &lt;a href=&quot;https://github.com/acherkashin/design-tokens-demo/blob/main/.github/workflows/ci.yml&quot;&gt;посмотреть здесь&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#storybook #automation #design #github&lt;/p&gt;</content:encoded></item><item><title>Последний год по пятницам я более-менее стабильно рекомендую статьи, которые стоит прочитать. Но на…</title><link>https://cherkashin.dev/posts/137/</link><guid isPermaLink="true">https://cherkashin.dev/posts/137/</guid><description>Последний год по пятницам я более-менее стабильно рекомендую статьи, которые стоит прочитать. Но на этой неделе у меня отпуск, поэтому рекомендую не статью, а приехать в Екатеринбург и прогуляться по набережной, где есть огромная клавиатура.

Но лучше летом, тут уже во всю зима 🥶

#vacation</description><pubDate>Fri, 27 Oct 2023 11:05:05 GMT</pubDate><content:encoded>&lt;p&gt;Последний год по пятницам я более-менее стабильно рекомендую статьи, которые стоит прочитать. Но на этой неделе у меня отпуск, поэтому рекомендую не статью, а приехать в Екатеринбург и прогуляться по набережной, где есть огромная клавиатура.&lt;/p&gt;
&lt;p&gt;Но лучше летом, тут уже во всю зима 🥶&lt;/p&gt;
&lt;p&gt;#vacation&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-137-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-137-1.jpg"/></item><item><title>​​💻️️️️️️ Array.prototype.sort</title><link>https://cherkashin.dev/posts/136/</link><guid isPermaLink="true">https://cherkashin.dev/posts/136/</guid><description>​​💻️️️️️️ Array.prototype.sort

Как будет отсортирован следующий массив [-1, 0, 1, 2, -1, -4, -2, -3, 3, 0, 4].sort()?

🥱 Предыстория

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

Я написал решение, подебажил н...</description><pubDate>Mon, 23 Oct 2023 08:01:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/65d4719a52cbfb1205993.jpg&quot;&gt;​​&lt;/a&gt;💻️️️️️️ &lt;strong&gt;Array.prototype.sort&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Как будет отсортирован следующий массив &lt;code&gt;[-1, 0, 1, 2, -1, -4, -2, -3, 3, 0, 4].sort()&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;🥱 &lt;strong&gt;Предыстория&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На выходных я решал литкод, и в задаче &lt;a href=&quot;https://leetcode.com/problems/3sum/&quot;&gt;3sum&lt;/a&gt; было необходимо отсортировать массив по возрастанию, перед тем как перейти к основной реализации алгоритма.&lt;/p&gt;
&lt;p&gt;Я написал решение, подебажил на бумаге — всё работает, отправляю код на проверку — не работает 🤷‍♂️. Перепроверяю всё глазами — ну должно же работать!&lt;/p&gt;
&lt;p&gt;Сдаюсь и начинаю дебажить в VS Code и вижу, что сортировка массива работает не так как я ожидал.&lt;/p&gt;
&lt;p&gt;ℹ️** Объяснение**&lt;/p&gt;
&lt;p&gt;Если перейти на MDN и прочитать документацию &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort&quot;&gt;Array.prototype.sort()&lt;/a&gt;, то станет всё понятно.&lt;/p&gt;
&lt;p&gt;Метод &lt;code&gt;sort()&lt;/code&gt; в JavaScript преобразует элементы в строки и затем сравнивает их последовательности значений кодов UTF-16. Это означает, что при сортировке числа рассматриваются как строки.&lt;/p&gt;
&lt;p&gt;Таким образом, числа в данном случае сортируются на основе их строкового представления. Например, ‘&lt;strong&gt;-10&lt;/strong&gt;’ будет идти перед ‘&lt;strong&gt;-2&lt;/strong&gt;’, потому что строка &lt;strong&gt;‘10’&lt;/strong&gt; идет перед строкой &lt;strong&gt;‘2’&lt;/strong&gt; в лексикографическом порядке.&lt;/p&gt;
&lt;p&gt;Чтобы выполнить числовую сортировку массива, нужно предоставить функцию сравнения методу &lt;code&gt;sort()&lt;/code&gt;, как показано здесь:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;sort&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; b);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Это даст вам &lt;code&gt;[-4, -3, -2, -1, -1, 0, 0, 1, 2, 3, 4]&lt;/code&gt; — числовую сортировку.&lt;/p&gt;
&lt;p&gt;#javascript #frontend #algorithms&lt;/p&gt;</content:encoded></item><item><title>📖 Обязан ли разработчик развиваться❓</title><link>https://cherkashin.dev/posts/135/</link><guid isPermaLink="true">https://cherkashin.dev/posts/135/</guid><description>📖 Обязан ли разработчик развиваться❓

Сегодня статья с названием, которое говорит само за себя, очень рекомендую к прочтению.

Естественно, никто никому ничего не должен, и нельзя говорить, что кто-то прям обязан развиваться. К тому же, не все горят разработкой, для некоторых это просто средство заработка, а для души ...</description><pubDate>Fri, 20 Oct 2023 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;a href=&quot;https://habr.com/ru/articles/686742/&quot;&gt;Обязан ли разработчик развиваться❓&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Сегодня статья с названием, которое говорит само за себя, очень рекомендую к прочтению.&lt;/p&gt;
&lt;p&gt;Естественно, никто никому ничего не должен, и нельзя говорить, что кто-то прям обязан развиваться. К тому же, не все горят разработкой, для некоторых это просто средство заработка, а для души они могут проводить свободное время за токарным станком.&lt;/p&gt;
&lt;p&gt;Но, как по мне, разработчику следует развиваться настолько, чтобы он мог качественно выполнять свою работу. Если же к твоей работе есть вопросы — придётся поднапрячься, не нужно быть обузой для своих коллег**.&lt;/p&gt;
&lt;p&gt;**К тому же, всё так быстро развивается, что скорее всего иногда придётся изучать что-то новое, чтобы не потерять работу вовсе.  **&lt;/p&gt;
&lt;p&gt;Основные моменты статьи:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;**Если вы джун — статья не для вас, опция доступна для мидлов и выше&lt;/li&gt;
&lt;li&gt;Разработчику следует развиваться, но &lt;strong&gt;не обязан&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Не все обязаны развиваться, можно просто хорошо делать свою работу&lt;/li&gt;
&lt;li&gt;Руководителям не стоит заставлять всех развиваться&lt;/li&gt;
&lt;li&gt;Не нужно развиваться 24/7. Учиться, развиваться нужно вдумчиво и постепенно — умеренность защитит вашу психику и приведёт к лучшим результатам. Иначе можно и &lt;a href=&quot;https://habr.com/ru/articles/468321/&quot;&gt;выгореть.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/articles/686742/&quot;&gt;https://habr.com/ru/articles/686742/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading  #burnout&lt;/p&gt;</content:encoded></item><item><title>⚛️ Атомарные обновления в Zustand</title><link>https://cherkashin.dev/posts/133/</link><guid isPermaLink="true">https://cherkashin.dev/posts/133/</guid><description>⚛️ Атомарные обновления в Zustand

Я уже упоминал атомарные обновления ранее, когда говорил о проблемах контекста реакта.

Я называю обновления атомарными, если компонент обновляется только тогда, когда изменяются данные, которые он использует. У контекста реакта с этим большие проблемы, но и при использовании Zustand ...</description><pubDate>Mon, 16 Oct 2023 08:00:07 GMT</pubDate><content:encoded>&lt;p&gt;⚛️ &lt;strong&gt;Атомарные обновления в Zustand&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я уже упоминал &lt;a href=&quot;https://t.me/cherkashindev/130&quot;&gt;атомарные обновления ранее&lt;/a&gt;, когда говорил о проблемах контекста реакта.&lt;/p&gt;
&lt;p&gt;Я называю обновления атомарными, если компонент обновляется только тогда, когда изменяются данные, которые он использует. У контекста реакта с этим большие проблемы, но и при использовании Zustand можно выстрелить себе в ногу.&lt;/p&gt;
&lt;p&gt;Zustand сравнивает по ссылке предыдущее и текущее значение, возвращаемое из &lt;code&gt;useStore()&lt;/code&gt;, и если объект изменился — происходит ре-рендер.&lt;/p&gt;
&lt;p&gt;❌ В следующем примере у нас всегда будет возвращаться новый объект, и ре-рендер произойдёт даже если изменился только &lt;code&gt;age&lt;/code&gt;, а &lt;code&gt;lastName&lt;/code&gt; и &lt;code&gt;firstName&lt;/code&gt; не изменились&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;firstName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;lastName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(({&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;firstName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;lastName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; ({firstName, lastName}));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Аналогичное поведение будет и в следующем случае&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;firstName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;lastName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;✅ Есть три варианта использования значений из стейта, которые поддерживают атомарные обновления:&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;strong&gt;Одиночные селекторы&lt;/strong&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; firstName&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.firstName)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; lastName&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; state.lastName)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;2️⃣ Селектор, который возвращает объект + shallow - функция сравнения предыдущего и нового стейтов&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;firstName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;lastName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; useStore&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(({&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;firstName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;lastName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}) &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    firstName, &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    lastName&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}), shallow);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;3️⃣ &lt;a href=&quot;https://github.com/pmndrs/zustand/blob/main/docs/guides/auto-generating-selectors.md&quot;&gt;Автосгенерированных селекторы&lt;/a&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; firstName&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; useStore.use.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;firstName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; lastName&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; useStore.use.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;lastName&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://codesandbox.io/s/zustand-updates-example-2cyk3k&quot;&gt;Накидал небольшую демку в Codesandbox&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#frontend #react #statemanagement #zustand&lt;/p&gt;</content:encoded></item><item><title>​​📖️️️️️️ Каррирование и частичное применение</title><link>https://cherkashin.dev/posts/132/</link><guid isPermaLink="true">https://cherkashin.dev/posts/132/</guid><description>​​📖️️️️️️ Каррирование и частичное применение

Каррирование и частичное применение — две концепции из функционального программирования, которые очень часто путают из-за их схожести (а я пишу этот пост, чтобы наконец-то запомнить).

И частичное применение, и каррирование, реализуются как функции, принимающие в качестве...</description><pubDate>Fri, 13 Oct 2023 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/f7ceaaa8eb3a1f232ec89.jpg&quot;&gt;​​&lt;/a&gt;📖️️️️️️ &lt;strong&gt;Каррирование и частичное применение&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Каррирование и частичное применение — две концепции из функционального программирования, которые очень часто путают из-за их схожести (а я пишу этот пост, чтобы наконец-то запомнить).&lt;/p&gt;
&lt;p&gt;И частичное применение, и каррирование, реализуются как функции, принимающие в качестве параметра другую функцию.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Частичное применение&lt;/strong&gt; — функция &lt;code&gt;partialApply&lt;/code&gt;, принимающая первым параметром функцию — &lt;code&gt;fn&lt;/code&gt;, а остальные параметры — часть параметров функции &lt;code&gt;fn&lt;/code&gt;. Функция &lt;code&gt;partialApply&lt;/code&gt; возвращает функцию, которая в качестве параметров принимает недостающие аргументы функции fn.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Каррирование&lt;/strong&gt; — функция &lt;code&gt;curry&lt;/code&gt;, которая принимает единственный параметр — функцию &lt;code&gt;fn&lt;/code&gt;, и возвращает каррированную функцию &lt;code&gt;fn&lt;/code&gt;.  Можно сказать, что каррированная функция &lt;code&gt;fn&lt;/code&gt; — функция аккумулятор, которая будет накапливать переданные аргументы до тех пор, пока не будет передано достаточно параметров для вызова исходной функции. Параметры можно передавать в любом количестве.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Подробнее&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/articles/143465/&quot;&gt;Карринг vs Частичное применение функции&lt;/a&gt; — C#&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/ruvds/articles/427295/&quot;&gt;Каррирование функций в JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.javascript.ru/currying-partials#prodvinutaya-realizatsiya-karrirovaniya&quot;&gt;Реализация функции каррирования&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length&quot;&gt;Function: length&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #frontend #javascript #functionalprogramming&lt;/p&gt;</content:encoded></item><item><title>🍂 Проваливание промисов</title><link>https://cherkashin.dev/posts/131/</link><guid isPermaLink="true">https://cherkashin.dev/posts/131/</guid><description>🍂 Проваливание промисов

Когда вы передаете в then() что-то отличное от функции (например, промис), это интерпретируется как then(null) и в следующий по цепочке промис «проваливается» результат предыдущего.

Подробнее о промисах в статье &quot;У нас проблемы с промисами&quot;.

#interview #frontend #javascript</description><pubDate>Mon, 09 Oct 2023 08:00:03 GMT</pubDate><content:encoded>&lt;p&gt;🍂 &lt;strong&gt;Проваливание промисов&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда вы передаете в &lt;code&gt;then()&lt;/code&gt; что-то отличное от функции (например, промис), это интерпретируется как &lt;code&gt;then(null)&lt;/code&gt; и в следующий по цепочке промис «проваливается» результат предыдущего.&lt;/p&gt;
&lt;p&gt;Подробнее о промисах в статье “&lt;a href=&quot;https://habr.com/ru/companies/vk/articles/269465/&quot;&gt;У нас проблемы с промисами&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;#interview #frontend #javascript&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-131-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-131-1.jpg"/></item><item><title>​​⚠️ Проблемы React Context</title><link>https://cherkashin.dev/posts/130/</link><guid isPermaLink="true">https://cherkashin.dev/posts/130/</guid><description>​​⚠️ Проблемы React Context

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

1️⃣ Дизайн по умолчанию, не совсем безопасен.

Логика хране...</description><pubDate>Fri, 06 Oct 2023 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/1a91ff7709608d5e42a51.jpg&quot;&gt;​​&lt;/a&gt;⚠️ &lt;strong&gt;Проблемы React Context&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Использование контекста реакта и хуков, упрощает управление состоянием приложения. В небольших проектах уж и вовсе позволяет отказаться от использования менеджеров состояний. Но у него есть ряд проблем, о которых необходимо знать.&lt;/p&gt;
&lt;p&gt;1️⃣ Дизайн по умолчанию, не совсем безопасен.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Логика хранения стейта и его изменения разбросана между контекстом и использующими его компонентами&lt;/li&gt;
&lt;li&gt;Значение &lt;code&gt;value&lt;/code&gt; контекста необходимо мемоизировать с помощью &lt;code&gt;useMemo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Если компонент, не нашёл контекст в родительских узлах — он будет молча использовать значения по-умолчанию. Мы не увидим никаких предупреждений или ошибок&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Эти проблемы и их решения рассматривается в статье &lt;a href=&quot;https://levelup.gitconnected.com/react-how-i-learned-to-create-optimized-contexts-e121dc232a95&quot;&gt;React: How I learned to create optimized contexts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✅ Вместо использования контекста напрямую, нужно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Указать &lt;code&gt;null&lt;/code&gt; в качестве значения по-умолчанию для контекста&lt;/li&gt;
&lt;li&gt;Реализовать &lt;code&gt;useSafeContext&lt;/code&gt; — кастомный хук, который будет проверять, что значение не &lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Реализовать &lt;code&gt;SafeContext&lt;/code&gt; — компонент, который содержит логику инициализации значения реакт контекста&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2️⃣ Отсутствие атомарных обновлений — компоненты или хуки, которые используют контекст, перерендеривается каждый раз, когда контекст изменяет состояние. Даже если ваш компонент использует лишь одной свойство из контекста, которое никогда не изменяется — компонент будет перерендериваться при изменении любого другого свойства в контексте.&lt;/p&gt;
&lt;p&gt;✅ Как решить проблему?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Не класть всё в один большой контекст, а разбить его на несколько маленьких&lt;/li&gt;
&lt;li&gt;Использовать библиотеку для управления состоянием, например, &lt;a href=&quot;https://t.me/cherkashindev/124&quot;&gt;zustand&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Минимизировать использование контекста. Например, можно использовать контекст в родительском компоненте, а дочерним передать нужные значения через пропсы.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Проблемы и решения описаны в статье &lt;a href=&quot;https://dev.to/leewarrickjr/the-problem-with-react-s-context-api-3dn0&quot;&gt;The Problem with React’s Context API&lt;/a&gt; (&lt;a href=&quot;https://dev.to/balaevarif/react-context-api-3h01&quot;&gt;тут перевод на русский&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;#fridayreading #react #frontend #statemanagement&lt;/p&gt;</content:encoded></item><item><title>👨‍💻Где проводить live-coding</title><link>https://cherkashin.dev/posts/129/</link><guid isPermaLink="true">https://cherkashin.dev/posts/129/</guid><description>👨‍💻Где проводить live-coding

Если вы время от времени проводите собеседования — то вы наверняка хотите не только поговорить о жизни с кандидатом, но и проверить насколько он хорош в деле. Для этого вам поможет live-кодинг.

Для live-кодинга, вы можете использовать:

1️⃣ Yandex Code
- ✅ Подсветка синтаксиса
- ✅ Совме...</description><pubDate>Mon, 02 Oct 2023 08:00:06 GMT</pubDate><content:encoded>&lt;p&gt;👨‍💻**Где проводить live-coding&lt;/p&gt;
&lt;p&gt;**Если вы время от времени проводите собеседования — то вы наверняка хотите не только поговорить о жизни с кандидатом, но и проверить насколько он хорош в деле. Для этого вам поможет live-кодинг.&lt;/p&gt;
&lt;p&gt;Для live-кодинга, вы можете использовать:&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;a href=&quot;https://code.yandex-team.ru/&quot;&gt;Yandex Code&lt;/a&gt;
- ✅ Подсветка синтаксиса
- ✅ Совместное написание кода
- ❌ Нет подсветки ошибок
- ❌ Нельзя запускать код&lt;/p&gt;
&lt;p&gt;2️⃣ &lt;a href=&quot;https://interview.cups.online/live-coding&quot;&gt;Interview Cups&lt;/a&gt; — онлайн редактор от VK
- ✅ Подсветка синтаксиса
- ✅ Совместное написание кода
- ❌ Подсветка ошибок
- ✅ Можно запускать код&lt;/p&gt;
&lt;p&gt;3️⃣ &lt;a href=&quot;https://visualstudio.microsoft.com/services/live-share/&quot;&gt;Visual Studio Live Share&lt;/a&gt;. Позволяет  кандидату открыть ваш проект прямо в браузере, после чего  вы можете совместно писать код.&lt;/p&gt;
&lt;p&gt;А что вы используете для live-кодинга?&lt;/p&gt;
&lt;p&gt;#interview #vscode #tools&lt;/p&gt;</content:encoded></item><item><title>​​📖 Архитектура фронтенда на основе вертикальных слайсов</title><link>https://cherkashin.dev/posts/128/</link><guid isPermaLink="true">https://cherkashin.dev/posts/128/</guid><description>​​📖 Архитектура фронтенда на основе вертикальных слайсов

Сегодня порекомендую статью о структуре фронтенд проектов на основе вертикальных слайсов.

Автор начинает рассказ с описания структур первых проектов, где использовался подход “Разделения по техническим слоям”, в котором мы группируем файлы по функциональности,...</description><pubDate>Fri, 29 Sep 2023 08:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/9cacadf0f91a7d38b58b9.jpg&quot;&gt;​​&lt;/a&gt;📖 &lt;a href=&quot;https://amorgunov.com/posts/2023-05-28-vertical-sliced-architecture-in-frontend/&quot;&gt;Архитектура фронтенда на основе вертикальных слайсов&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Сегодня порекомендую статью о структуре фронтенд проектов на основе вертикальных слайсов.&lt;/p&gt;
&lt;p&gt;Автор начинает рассказ с описания структур первых проектов, где использовался подход “Разделения по техническим слоям”, в котором мы группируем файлы по функциональности, а не по доменной области:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;api/services&lt;/li&gt;
&lt;li&gt;components&lt;/li&gt;
&lt;li&gt;stores&lt;/li&gt;
&lt;li&gt;constants&lt;/li&gt;
&lt;li&gt;и т.д.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;и затем описывается, как этот подход всё ещё используется внутри “вертикальных слайсов”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Разделение по техническим слоям&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;✅ &lt;strong&gt;Плюсы подхода&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;хорошо работает для маленьких проектов&lt;/li&gt;
&lt;li&gt;у слоев есть однонаправленный поток использования, и нельзя импортировать файлы из слоев, находящихся на уровне выше (например сторы могут использовать api, а страницы могут использовать базовые компоненты, но не наоборот).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;❌ &lt;strong&gt;Проблемы подхода&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Даже для небольших продуктовых фичей приходится править код по всему проекту, так как он раскидан по разным папкам&lt;/li&gt;
&lt;li&gt;Неявные связи в рамках конкретных слоев: бизнес компоненты (ProductCard, UserProfile) смешиваются c UI компонентами (Link, Button) в &lt;strong&gt;components&lt;/strong&gt;, то же самое касается бизнес логики&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;«Vertical sliced» подход&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Подход подразумевает, что архитектура строится не вокруг технических слоев, а поверх конкретных слайсов проекта.&lt;/p&gt;
&lt;p&gt;По сути, мы берём структуру “разделения по техническим слоям” и делаем разрез по фичам. То есть, создаём папку для каждой фичи, внутри которой все файлы относятся только к этой фиче и “разделены по техническим слоям”.&lt;/p&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;Описание папок&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;shared - тут хранятся всё,  что можно переиспользовать и не зависит от определённой бизнес фичи. Например в &lt;code&gt;shared/components&lt;/code&gt; будут лежать, обычные кнопки, радио кнопки и прочее&lt;/li&gt;
&lt;li&gt;domain - базовый UI для бизнес-сущностей (домена) проекта, например карточка товара. Простая аналогия (но не совсем правильная) - в домене можно хранить все то, что хранится в базе данных на бекенде.&lt;/li&gt;
&lt;li&gt;features - самодостаточные компоненты — большие бизнес сущности приложения, например корзина. Для реализации фичи, скорее всего будет использоваться несколько компонентов из доменной области.&lt;/li&gt;
&lt;li&gt;pages - страницы приложения.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✅ &lt;strong&gt;Плюсы подхода&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Когда необходимо внести изменения в фичу — все изменения происходят внутри одного слайса.&lt;/li&gt;
&lt;li&gt;На выходе &lt;strong&gt;получаем высокое зацепление (&lt;strong&gt;high cohesion&lt;/strong&gt;) внутри слайса и низкую связанность (&lt;strong&gt;low coupling&lt;/strong&gt;) между разными слайсами&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Сохраняется правило однонапревленного использвания: pages ⇒ features ⇒ domain ⇒ shared&lt;/li&gt;
&lt;li&gt;Фичи не могут напрямую использовать друг друга&lt;/li&gt;
&lt;li&gt;На самом нижнем уровне используется “разделение по техническим слоям”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Чтобы обеспечить однонаправленный поток использования можно взять &lt;a href=&quot;https://t.me/cherkashindev/92&quot;&gt;eslint c плагином import/no-restricted-paths&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#frontend #architecture #fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​Как тестировать internal методы и классы в C# — InternalsVisibleToAttribute</title><link>https://cherkashin.dev/posts/127/</link><guid isPermaLink="true">https://cherkashin.dev/posts/127/</guid><description>​​Как тестировать internal методы и классы в C# — InternalsVisibleToAttribute

Представьте, что вы разрабатываете библиотеку, которой будут пользоваться тысячи людей 😮. Чтобы убедиться в стабильности — нужно всё хорошенько покрыть тестами. Все мы любим инкапсуляцию, верно (я надеюсь)? Поэтому мы не разрешаем использов...</description><pubDate>Mon, 25 Sep 2023 08:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/94c154a2c495db7586841.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Как тестировать internal методы и классы в C# — InternalsVisibleToAttribute&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Представьте, что вы разрабатываете библиотеку, которой будут пользоваться тысячи людей 😮. Чтобы убедиться в стабильности — нужно всё хорошенько покрыть тестами. Все мы любим инкапсуляцию, верно (я надеюсь)? Поэтому мы не разрешаем использовать всё подряд из нашей сборки, а с умом используем модификаторы доступа и позволяем использовать только &lt;code&gt;public&lt;/code&gt; классы и методы.&lt;/p&gt;
&lt;p&gt;В C#, есть 7 модификаторов доступа, основные:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;private&lt;/code&gt; —  доступ только внутри текущего класса&lt;/li&gt;
&lt;li&gt;&lt;code&gt;protected&lt;/code&gt; —  доступ внутри текущего и дочерних классов&lt;/li&gt;
&lt;li&gt;&lt;code&gt;public&lt;/code&gt; — классы и методы доступны где угодно, также из сборок, использующих текущую&lt;/li&gt;
&lt;li&gt;&lt;code&gt;internal&lt;/code&gt; — публичный API, внутри текущей сборки. Как &lt;code&gt;public&lt;/code&gt;, но нет доступа из сборок использующих текущую&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://metanit.com/sharp/tutorial/3.2.php&quot;&gt;остальные можно посмотреть тут&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Но, C# — не JavaScript, и для тестов создаётся отдельная сборка, а &lt;code&gt;internal&lt;/code&gt; методы в ней не доступны.&lt;/p&gt;
&lt;p&gt;Чтобы тестировать &lt;code&gt;internal&lt;/code&gt; функциональность, нужно использовать атрибут &lt;code&gt;InternalsVisibleToAttribute&lt;/code&gt;, и в качестве параметра указать имя тестовой сборки. Тогда все &lt;code&gt;internal&lt;/code&gt; методы и классы будут доступны для тестирования.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[assembly: InternalsVisibleToAttribute(&quot;YourProject.UnitTests&quot;)]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;#tests #dotnet&lt;/p&gt;</content:encoded></item><item><title>Все побежали просить пробустить канал, а я что хуже?</title><link>https://cherkashin.dev/posts/126/</link><guid isPermaLink="true">https://cherkashin.dev/posts/126/</guid><description>Все побежали просить пробустить канал, а я что хуже?

https://t.me/cherkashindev?boost</description><pubDate>Fri, 22 Sep 2023 16:23:45 GMT</pubDate><content:encoded>&lt;p&gt;Все побежали просить пробустить канал, а я что хуже?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev?boost&quot;&gt;https://t.me/cherkashindev?boost&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-126-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-126-1.jpg"/></item><item><title>Собирайте свои достижения</title><link>https://cherkashin.dev/posts/125/</link><guid isPermaLink="true">https://cherkashin.dev/posts/125/</guid><description>Собирайте свои достижения

❓Зачем

Поможет наполнить ваше резюме фактами и более убедительно презентовать себя на собеседованииПоможет понять вам кто вы есть. Если у вас достижения уровня Джуна — то вы врядли Сеньор помидорПоможет понять двигаетесь ли вы в правильном направлении. Достижения играют роль отметок на вашей...</description><pubDate>Fri, 22 Sep 2023 08:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Собирайте свои достижения&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;❓&lt;strong&gt;Зачем&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Поможет наполнить ваше резюме фактами и более убедительно презентовать себя на собеседовании&lt;/li&gt;
&lt;li&gt;Поможет понять вам кто вы есть. Если у вас достижения уровня Джуна — то вы врядли Сеньор помидор&lt;/li&gt;
&lt;li&gt;Поможет понять двигаетесь ли вы в правильном направлении. Достижения играют роль отметок на вашей внутренней карте — взглянув на них, вы понимаете, откуда, куда и как долго вы шли&lt;/li&gt;
&lt;li&gt;Поможет получить визу талантов. Ну а вдруг 🤷‍♂️&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;❓&lt;strong&gt;Как&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Записывать достижения в формате:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Дата или период времени, за который достигнут определённый результат&lt;/li&gt;
&lt;li&gt;Суть достижения и ваша роль в нём&lt;/li&gt;
&lt;li&gt;Количественные метрики этого достижения&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ℹ️ Например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Время: март 2021 года.&lt;/li&gt;
&lt;li&gt;Суть: запустил новую монетизацию в блог-платформе Spiritualist.&lt;/li&gt;
&lt;li&gt;Метрики: выручка увеличилась на 5%, рейтинг приложения в сторе вырос с 2,5 до 4,2.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Записывать всё это можно в Notion, Google Docs, в обычном текстовом файле, куда хотите. К тому же, нужно завести папку, куда вы будете складывать подтверждения этих метрик:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Публикации об этих достижениях компании/продукта в новостных изданиях.&lt;/li&gt;
&lt;li&gt;Скриншоты метрик из Grafana.&lt;/li&gt;
&lt;li&gt;Письмо руководителя о том, какой вы классный.&lt;/li&gt;
&lt;li&gt;Отчёт c Performance Review.&lt;/li&gt;
&lt;li&gt;Зарплатный квиток с указанием премии.&lt;/li&gt;
&lt;li&gt;Скрин с презентации, где руководство говорит о вашем достижении.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;#fridayreading&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/articles/714426/&quot;&gt;https://habr.com/ru/articles/714426/&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>​​Почему мы выбрали Zustand❓</title><link>https://cherkashin.dev/posts/124/</link><guid isPermaLink="true">https://cherkashin.dev/posts/124/</guid><description>​​Почему мы выбрали Zustand❓

Как я упомянул в предыдущем посте о Zustand, мы начали его использовать в июне 2021 года.

До этого использовали просто useState/useReducer/useContext, поняли что так больше нельзя, и перед разработкой новой большой фичи мы начали искать подходящий менеджер состояний. У нас были следующие ...</description><pubDate>Mon, 18 Sep 2023 08:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/90fce12eb433cce9d20ad.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Почему мы выбрали Zustand&lt;/strong&gt;❓&lt;/p&gt;
&lt;p&gt;Как я упомянул в &lt;a href=&quot;https://t.me/cherkashindev/120&quot;&gt;предыдущем посте о Zustand&lt;/a&gt;, мы начали его использовать в июне 2021 года.&lt;/p&gt;
&lt;p&gt;До этого использовали просто useState/useReducer/useContext, поняли что так больше нельзя, и перед разработкой новой большой фичи мы начали искать подходящий менеджер состояний. У нас были следующие требования:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Использование состояния между компонентами, у которых нет общего родительского компонента. Мы мигрируем с JQuery на React, поэтому большинство компонентов рендерятся с помощью &lt;a href=&quot;https://react.dev/reference/react-dom/client/createRoot&quot;&gt;createRoot&lt;/a&gt; и не имеют общего родителя, что не позволяет использовать контекст реакта и совместно использовать состояние между компонентами&lt;/li&gt;
&lt;li&gt;Атомарные обновления, чего нет у контекста реакта&lt;/li&gt;
&lt;li&gt;Поддержка асинхронных обновлений стейта вне компонента. Чтобы избегать ошибок типа &lt;code&gt;Can&apos;t perform a React state update on an unmounted component&lt;/code&gt;, которые происходят, когда обновляется состояние для уже удалённого компонента&lt;/li&gt;
&lt;li&gt;Поддержка Computed Properties&lt;/li&gt;
&lt;li&gt;Поддержка TypeScript&lt;/li&gt;
&lt;li&gt;Тестируемость&lt;/li&gt;
&lt;li&gt;Маленький размер бандла&lt;/li&gt;
&lt;li&gt;Англоязычное комьюнити, потому что команда англоязычная&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;И следующий 2 требования я выделю отдельно:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Простота использования.&lt;/strong&gt; Очень важно, когда у вас разработчики со всех концов света и скилы у всех разные. К тому же, очень просто наговнокодить, когда вы начинаете использовать новый инструмент.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Возможность использовать вне реакта.&lt;/strong&gt; Как я уже упомянул, мы мигрируем с JQuery на React, поэтому мы хотели использовать стейт менеджер и в легаси коде. Это позволило бы:
&lt;ul&gt;
&lt;li&gt;мигрировать глобальный стейт в новую кодовую базу и использовать во всём приложении&lt;/li&gt;
&lt;li&gt;управлять реакт компонентами из JQuery, просто меняя стейт.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1️⃣ В первоначальном списке оказались:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Redux&lt;/li&gt;
&lt;li&gt;MobX&lt;/li&gt;
&lt;li&gt;Recoil&lt;/li&gt;
&lt;li&gt;Zustand&lt;/li&gt;
&lt;li&gt;Jotai&lt;/li&gt;
&lt;li&gt;Akita&lt;/li&gt;
&lt;li&gt;Effector&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2️⃣ После анализа, в следующем раунде отбора оказались: MobX, Recoil и Zustand. Recoil попал &lt;strong&gt;по блату&lt;/strong&gt;, его проталкивал один из членов команды, и потому что он разработан в стенах авторитетной “запрещённой” организации.&lt;/p&gt;
&lt;p&gt;Мы переписали один и тот же небольшой компонент на MobX, Recoil и Zustand, чтобы проверить их в деле:&lt;/p&gt;
&lt;p&gt;❌  MobX. По большей части нам не понравилось, что каждый компонент нужно оборачивать в &lt;a href=&quot;https://mobx.js.org/react-integration.html&quot;&gt;observer&lt;/a&gt;, если он использует &lt;a href=&quot;https://mobx.js.org/observable-state.html&quot;&gt;observable&lt;/a&gt; объект. К тому же, у него не самый простой API.&lt;/p&gt;
&lt;p&gt;❌  К Recoil было очень много вопросов. Начиная от того, что он жирный — почти &lt;a href=&quot;https://bundlephobia.com/package/recoil@0.7.7&quot;&gt;80Кб без GZip&lt;/a&gt; и заканчиваю тем, что нельзя просто взять и вынести из компонента асинхронные обновления стейта. С асинхронным получением данных всё понятно, там есть &lt;a href=&quot;https://recoiljs.org/docs/basic-tutorial/selectors&quot;&gt;селекторы&lt;/a&gt;, но как асинхронно обновить стейт — хз. К тому же он не production ready.&lt;/p&gt;
&lt;p&gt;✅ Zustand нам понравился своей простотой, чтобы понять код – даже не нужно смотреть документацию. Также круто, что он удовлетворял буквально каждому нашему требованию.&lt;/p&gt;
&lt;p&gt;Если вы ещё не знакомы с Zustand, то обязательно посмотрите &lt;a href=&quot;https://t.me/cherkashindev/120&quot;&gt;видео из предыдущего поста&lt;/a&gt;. А если вам в целом интересна тема стейт менеджеров — то подписывайтесь на &lt;a href=&quot;https://t.me/artalog&quot;&gt;Артёма — автора реатома&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;P.S. Кстати, Zustand прост не только в использовании, его исходники тоже просты как дважды два — четыре. Лучше понять, как он работает под капотом поможет статья &lt;a href=&quot;https://habr.com/ru/articles/750716/&quot;&gt;Как работает Zustand&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#frontend #react #statemanagement #zustand&lt;/p&gt;</content:encoded></item><item><title>📖 Доводите свои проекты до конца</title><link>https://cherkashin.dev/posts/123/</link><guid isPermaLink="true">https://cherkashin.dev/posts/123/</guid><description>📖 Доводите свои проекты до конца

Если вы постоянно начинаете новые проекты, не завершив предыдущие — эта статья для вас.

Автор не делится, никакими секретами, как доводить проекты до конца, потому что их просто нет. В любом проекте есть 10% неприятной рутинной работы, которые отнимают больше сил, чем предыдущие 90%....</description><pubDate>Fri, 15 Sep 2023 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Доводите свои проекты до конца&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Если вы постоянно начинаете новые проекты, не завершив предыдущие — &lt;a href=&quot;https://habr.com/ru/companies/ruvds/articles/745270/&quot;&gt;эта статья для вас&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Автор не делится, никакими секретами, как доводить проекты до конца, потому что их просто нет. В любом проекте есть 10% неприятной рутинной работы, которые отнимают больше сил, чем предыдущие 90%.  И именно эти 10% процентов стоят между вами и удовлетворённостью от завершённого проекта.&lt;/p&gt;
&lt;p&gt;Система, которая работает для автора, очень проста:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Выделите промежуток времени.&lt;/li&gt;
&lt;li&gt;Заранее решите, над чем будете работать.&lt;/li&gt;
&lt;li&gt;Всеми силами стремитесь сосредоточиться на этом единственном аспекте.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Автор рекомендует использовать любые приёмы, которые помогут вам сосредоточиться на оставшихся 10%.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ему помогает слушать одну и ту же песню, чтобы сосредоточиться.&lt;/li&gt;
&lt;li&gt;Мне немного помогает перетаскивать карточки из левой части в столбец “Done” и видеть, что я не стою на месте — процесс идёт.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;После того как вы завершите 10 процентов оставшейся работы, вы столкнётесь с другой проблемой, которая не даёт вам закончить проект — страх подвергнуть свою работу и &lt;strong&gt;себя&lt;/strong&gt; критике.&lt;/p&gt;
&lt;p&gt;Но у вас есть обязанность перед прошлым собой выпустить проект. Это способ отдать должное своей работе и жертвам. Ведь, всё потраченное на проект время можно было потратить на что-то другое. За это время вам пришлось чем-то пожертвовать.&lt;/p&gt;
&lt;p&gt;А как часто вы не доводите до конца свои проекты?&lt;/p&gt;
&lt;p&gt;#gtd #habr #fridayreading&lt;/p&gt;</content:encoded></item><item><title>С уходящим днем программиста, народ! 👨‍💻</title><link>https://cherkashin.dev/posts/122/</link><guid isPermaLink="true">https://cherkashin.dev/posts/122/</guid><description>С уходящим днем программиста, народ! 👨‍💻</description><pubDate>Wed, 13 Sep 2023 19:48:49 GMT</pubDate><content:encoded>&lt;p&gt;С уходящим днем программиста, народ! 👨‍💻&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-122-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-122-1.jpg"/></item><item><title>git blame —ignore-rev</title><link>https://cherkashin.dev/posts/121/</link><guid isPermaLink="true">https://cherkashin.dev/posts/121/</guid><description>git blame —ignore-rev

Пару месяцев назад, я читал статью о том, как команда TypeScript мигрировала с пространств имён на модули. Естественно, миграция происходила не вручную, а с помощью их внутренней тулзы (насколько я помню). И одной из проблем после такой массированной миграции (которая несёт лишь синтаксические из...</description><pubDate>Mon, 11 Sep 2023 10:02:45 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;git blame —ignore-rev&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Пару месяцев назад, я читал статью о том, как &lt;a href=&quot;https://devblogs.microsoft.com/typescript/typescripts-migration-to-modules/#wait-what-was-that-about-git&quot;&gt;команда TypeScript мигрировала с пространств имён на модули&lt;/a&gt;. Естественно, миграция происходила не вручную, а с помощью их внутренней тулзы (насколько я помню). И одной из проблем после такой массированной миграции (которая несёт лишь синтаксические изменения), &lt;strong&gt;является потеря истории `git blame`&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;🔍 Наверняка вы сталкивались с подобной проблемой в своих проектах. Когда в следующий раз вы попробуете использовать &lt;code&gt;git blame&lt;/code&gt;, то увидите, что множество строк в файле помечены коммитом с вашим рефакторингом. Теперь, чтобы найти реальный коммит, в котором была изменена строка, вам придётся переключиться на коммит до рефакторинга и ещё раз выполнить &lt;code&gt;git blame&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;🛡️ Чтобы не страдать, в гит добавили две опции &lt;code&gt;--ignore-rev&lt;/code&gt; и &lt;code&gt;--ignore-revs-file&lt;/code&gt;, которые скажут  &lt;code&gt;git blame&lt;/code&gt; , чтобы он вывел историю так, как будто этих коммитов никогда и не было.  Строки, которые были изменены или добавлены игнорируемым коммитом, будут связаны с предыдущим коммитом, который изменил эту строку или близлежащие строки. Теперь можете не бояться потерять историю во время рефакторинга!&lt;/p&gt;
&lt;p&gt;❗️К сожалению, не получится проигнорировать коммиты, если вы переносили файлы из одной папки в другую.&lt;/p&gt;
&lt;p&gt;🔗 Подробнее можете прочитать здесь — &lt;a href=&quot;https://moxio.com/blog/ignoring-bulk-change-commits-with-git-blame/&quot;&gt;Ignoring bulk change commits with git blame&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#git #lifehack&lt;/p&gt;</content:encoded></item><item><title>Zustand — очень простая альтернатива Redux и MobX, не сильно сложнее useReducer.</title><link>https://cherkashin.dev/posts/120/</link><guid isPermaLink="true">https://cherkashin.dev/posts/120/</guid><description>Zustand — очень простая альтернатива Redux и MobX, не сильно сложнее useReducer.

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

Если вы пропустили — то делюсь видео от Елены Литвин...</description><pubDate>Sat, 09 Sep 2023 08:26:15 GMT</pubDate><content:encoded>&lt;p&gt;Zustand — очень простая альтернатива Redux и MobX, не сильно сложнее useReducer.&lt;/p&gt;
&lt;p&gt;В последние пару лет появилось довольно много русскоязычных видео о Zustand. Мы на работе как раз начали его использовать пару лет назад, и в то время, похоже, он был не так популярен.&lt;/p&gt;
&lt;p&gt;Если вы пропустили — то делюсь видео от &lt;a href=&quot;https://t.me/webelart&quot;&gt;Елены Литвиновой&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=GNnEtOC4alQ&amp;#x26;ab_channel=HolyJS&quot;&gt;Holy JS: Елена Литвинова — Zustand: выскочка или серьезная альтернатива Redux? (Часть 1)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=o4UTnrXmgac&amp;#x26;ab_channel=HolyJS&quot;&gt;Holy JS: Елена Литвинова — Zustand: выскочка или серьезная альтернатива Redux? (Часть 2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=lf32_XjKxxo&amp;#x26;t=109s&amp;#x26;ab_channel=%D0%95%D0%BB%D0%B5%D0%BD%D0%B0%D0%9B%D0%B8%D1%82%D0%B2%D0%B8%D0%BD%D0%BE%D0%B2%D0%B0%E2%80%94%D0%98%D1%81%D0%BA%D1%83%D1%81%D1%81%D1%82%D0%B2%D0%BE%D0%B2%D0%B5%D0%B1-%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B8&quot;&gt;Подробно изучаем Zustand State Management (React, TypeScript)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend #react #statemanagement #zustand #fridayreading&lt;/p&gt;</content:encoded></item><item><title>Решил устроить себе “телеграммный” отпуск в августе и ничего не публиковать. Понял, что довольно…</title><link>https://cherkashin.dev/posts/119/</link><guid isPermaLink="true">https://cherkashin.dev/posts/119/</guid><description>Решил устроить себе “телеграммный” отпуск в августе и ничего не публиковать. Понял, что довольно много сил уходит на написание постов, прям как маленькая подработка.

Но я не всё время отдыхал, написал статью на хабр о сборщике мусора в .NET — Бессильный сборщик мусора или неуправляемая память в .NET. В сентябре буду и...</description><pubDate>Mon, 04 Sep 2023 07:01:50 GMT</pubDate><content:encoded>&lt;p&gt;Решил устроить себе “телеграммный” отпуск в августе и ничего не публиковать. Понял, что довольно много сил уходит на написание постов, прям как маленькая подработка.&lt;/p&gt;
&lt;p&gt;Но я не всё время отдыхал, написал статью на хабр о сборщике мусора в .NET — &lt;a href=&quot;https://habr.com/ru/articles/754248/&quot;&gt;Бессильный сборщик мусора или неуправляемая память в .NET&lt;/a&gt;. В сентябре буду исправляться.&lt;/p&gt;
&lt;p&gt;||Кстати, на Хабре обновили донаты, подключил, но не знаю, работают ли, хочет кто-нибудь потестировать? 😄 Листайте в конец статьи и найдёте там кнопку “Задонатить” 😉. ||&lt;/p&gt;
&lt;p&gt;#habr #csharp #dotnet #gc&lt;/p&gt;</content:encoded></item><item><title>Бессильный сборщик мусора или неуправляемая память в .NET</title><link>https://cherkashin.dev/articles/unmanaged-memory-dotnet/</link><guid isPermaLink="true">https://cherkashin.dev/articles/unmanaged-memory-dotnet/</guid><description>Если вы готовитесь к собеседованию и гуглите список вопросов для кандидата на C# разработчика, то сто процентов один из вопросов будет о сборщике мусора. На собеседованиях этот вопрос действительно частенько задают, но как только они заканчиваются, магическим образом все знания улетучиваются, прямо как после экзамена. Долгое время я не понимал, зачем мне нужно знать как именно работает сборщик мусора, ну собирает он как-то мусор, ну и пусть собирает дальше. Так я думал пока я не столкнулся с проблемами потребления памяти. Сегодня я хочу рассказать об одной из таких проблем, связанных с неуправляемой памятью.</description><pubDate>Tue, 15 Aug 2023 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/unmanaged-memory-dotnet/image1.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/unmanaged-memory-dotnet/image1.png"/></item><item><title>​​🗑️ Сборщик мусора в .NET🗑️</title><link>https://cherkashin.dev/posts/117/</link><guid isPermaLink="true">https://cherkashin.dev/posts/117/</guid><description>​​🗑️ Сборщик мусора в .NET🗑️

Одним из самых популярных на собеседованиях C# разработчиков является вопрос о работе сборщика мусора в .NET. Мне также приходилось рассказывать о нём интервьюерам на моих собесах. Сегодня я хотел бы кратко рассказать о сборщике мусора, заодно и сам вспомню.

🔍 Зачем нужен сборщик мусор...</description><pubDate>Mon, 14 Aug 2023 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/7180b9b48f1d79a3e8b60.jpg&quot;&gt;​​&lt;/a&gt;🗑️ &lt;strong&gt;Сборщик мусора в .NET&lt;/strong&gt;🗑️&lt;/p&gt;
&lt;p&gt;Одним из самых популярных на собеседованиях C# разработчиков является вопрос о работе сборщика мусора в .NET. Мне также приходилось рассказывать о нём интервьюерам на моих собесах. Сегодня я хотел бы кратко рассказать о сборщике мусора, заодно и сам вспомню.&lt;/p&gt;
&lt;p&gt;🔍 &lt;strong&gt;Зачем нужен сборщик мусора?&lt;/strong&gt;
Сборщик мусора автоматически обеспечивает освобождение памяти, занятой объектами, которые больше не используются. Такой подход предотвращает утечки памяти и снимает с разработчика бремя ручного освобождения памяти (привет С++), что позволяет сосредотачиваться на более важных аспектах программирования.&lt;/p&gt;
&lt;p&gt;⏰ &lt;strong&gt;Когда вызывается сборщик мусора?&lt;/strong&gt;
Сборщик мусора активируется автоматически, например, когда одно из поколений заполнено (о поколениях позже). Если вам требуется инициировать сборку мусора вручную, используйте GC.Collect().&lt;/p&gt;
&lt;p&gt;🔗 &lt;strong&gt;Как определяется, какие объекты больше не используются?&lt;/strong&gt;
Сборщик мусора опирается на концепцию “GC Roots” (корни сборки мусора):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Локальные переменные: Объекты, на которые существуют ссылки в локальных переменных.&lt;/li&gt;
&lt;li&gt;Статические переменные: Объекты, на которые ссылаются статические переменные классов. Эти корни живут в течение всего времени выполнения приложения.&lt;/li&gt;
&lt;li&gt;Активные элементы стека: Если во время выполнения функции происходит сборка мусора, то локальная переменная внутри данной функции не будет удалена сборщиком мусора. Такая переменная считается активным корнем, до тех пор пока кадр стека метода не будет разрушен.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Сборщик мусора создаёт граф (фаза маркировки), который содержит все объекты, достижимые из GC Roots. Объекты, на которые нет ссылок из GC Roots, считаются недостижимыми и готовыми для удаления.&lt;/p&gt;
&lt;p&gt;🔄 &lt;strong&gt;Как работает сборщик мусора?&lt;/strong&gt;
Сборщик мусора использует концепцию поколений (поколения 0, 1 и 2) для эффективной работы с объектами различной “старости”.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;При создании объекты помещаются в поколение 0. Если объект слишком большой (по умолчанию объекты размером больше 85 000 байт), то он будет помещён в Large Object Heap (очищается вместе с поколением 2).&lt;/li&gt;
&lt;li&gt;Когда поколение 0 заполнено — запускается сборка мусора. Неиспользуемые объекты удаляются (недостижимые из GC Roots), оставшиеся перемещаются в поколение 1.&lt;/li&gt;
&lt;li&gt;Аналогично происходит сборка мусора, когда заполнено поколение 1. Все выжившие объекты перемещаются в поколение 2. Затем происходит сборка мусора в поколении 0.&lt;/li&gt;
&lt;li&gt;Когда заполнено поколение 2, происходит полная сборка мусора. Сперва очищается поколение 2, а затем 1 и 0. Если после этого недостаточно места для новых объектов — происходит исключение OutOfMemory.&lt;/li&gt;
&lt;li&gt;В самом конце происходит фаза сжатия, в которой сборщик мусора перемещает живые объекты так, чтобы они располагались в памяти непосредственно друг за другом.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🔄  &lt;strong&gt;Для чего нужно разделение на несколько поколений?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сборка мусора поколения 0 выполняется чаще и занимается удалением объектов, которые быстро выходят из области видимости.&lt;/li&gt;
&lt;li&gt;С увеличением поколения редкость запуска сборки позволяет более эффективно использовать ресурсы. Поколение 0 очищается чаще всего, поколение 2 очищается реже всего.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🌐 &lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/help/dotmemory/NET_Memory_Management_Concepts.html&quot;&gt;.NET Memory Management Concepts&lt;/a&gt; — очень кратко об основных концепциях сборщика мусора&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://professorweb.ru/my/csharp/optimization/level3/3_4.php&quot;&gt;Поколения объектов&lt;/a&gt; — одна из очень подробного цикла статей о сборщике мусора&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#csharp #dotnet #gc #interview&lt;/p&gt;</content:encoded></item><item><title>​​TypeScript — satisfy или as</title><link>https://cherkashin.dev/posts/116/</link><guid isPermaLink="true">https://cherkashin.dev/posts/116/</guid><description>​​TypeScript — satisfy или as

Я думаю все знают о ключевом слове as в TypeScript. Мы используем его, когда нужно явно указать тип выражения, будь то переменная или функция. Когда мы используем as, происходит изменение типа выражения.

В TypeScript 4.9 появился оператор satisfies, который похож на оператор as, но работ...</description><pubDate>Fri, 28 Jul 2023 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/5fb111d709a2f4391c22c.jpg&quot;&gt;​​&lt;/a&gt;**TypeScript — satisfy или as&lt;/p&gt;
&lt;p&gt;**Я думаю все знают &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions&quot;&gt;о ключевом слове `as` в TypeScript&lt;/a&gt;. Мы используем его, когда нужно явно указать тип выражения, будь то переменная или функция. &lt;strong&gt;Когда мы используем `as`, происходит изменение типа выражения.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В TypeScript 4.9 появился оператор &lt;code&gt;satisfies&lt;/code&gt;, который похож на оператор &lt;code&gt;as&lt;/code&gt;, но работает немного иначе.&lt;/p&gt;
&lt;p&gt;ℹ️ Он также &lt;strong&gt;проверяет, что выражение соответствует типу, но не изменяет его (тип)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Разницу легко увидеть на картинке.&lt;/p&gt;
&lt;p&gt;При использовании &lt;code&gt;as&lt;/code&gt; изменяется тип на &lt;code&gt;Color&lt;/code&gt;, и мы теряем информацию об исходном типе объекта. Поэтому у нас появляется ошибка в месте вызова &lt;code&gt;myColor.value.toUpperCase()&lt;/code&gt; , потому что компилятор думает, что &lt;code&gt;value&lt;/code&gt; может быть также типа &lt;code&gt;RGB&lt;/code&gt;, у которого нет метода &lt;code&gt;toUpperCase&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;При использовании &lt;code&gt;satisfies&lt;/code&gt; ошибки нет, потому что исходная информация о типе сохранена.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@cefn/typescript-satisfies-6ba52e74cb2f&quot;&gt;Typescript’s new ‘satisfies’ operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://devblogs.microsoft.com/typescript/announcing-typescript-4-9-beta/#the-satisfies-operator&quot;&gt;Announcing TypeScript 4.9 Beta — The `satisfies` Operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#typescript&lt;/p&gt;</content:encoded></item><item><title>Бинарная куча и приоритетная очередь</title><link>https://cherkashin.dev/posts/115/</link><guid isPermaLink="true">https://cherkashin.dev/posts/115/</guid><description>Бинарная куча и приоритетная очередь

Последние пару месяцев я решил попрактиковаться в решении задач на алгоритмы и структуры данных и вспомнить всё, что мы проходили в универе. Там, кстати, ни слова не было не только о сложностях алгоритмов, но и о Приоритетных очередях.

❓ Что это такое “Приоритетная очередь”

Приор...</description><pubDate>Mon, 24 Jul 2023 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Бинарная куча и приоритетная очередь&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Последние пару месяцев я решил попрактиковаться в решении задач на алгоритмы и структуры данных и вспомнить всё, что мы проходили в универе. Там, кстати, ни слова не было не только о сложностях алгоритмов, но и о Приоритетных очередях.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;❓ Что это такое “Приоритетная очередь”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Приоритетная очередь — это коллекция, в которой, в отличии от обычной очереди, элементы упорядочиваются не на основе того, когда был добавлен элемент, а на основе приоритета, который этот элемент имеет. То есть, первым всегда будет извлекаться элемент с максимальным приоритетом. Также можно настроить очередь, чтобы она работала с наименьшими приоритетами.&lt;/p&gt;
&lt;p&gt;Приоритетная очередь поддерживает те же операции, что и обычная очередь.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;❓ Что это такое “Бинарная (двоичная) куча”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Бинарная куча –  структура данных, позволяющая быстро (за логарифмическое время) добавлять элементы и извлекать элемент с максимальным приоритетом.&lt;/p&gt;
&lt;p&gt;Куча представляет собой полное бинарное дерево, в котором каждый элемент не меньше своих потомков. Таким образом, максимальный элемент всегда находится в корне, поэтому доступ к нему происходит за &lt;strong&gt;O&lt;/strong&gt;(1)&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Можно сказать, что приоритетная очередь — это интерфейс, а бинарная куча — одна из возможных реализаций интерфейса “приоритетной очереди”.&lt;/p&gt;
&lt;p&gt;💡 О том, как происходит добавление и удаление элементов из бинарной кучи описано в статье на хабре &lt;a href=&quot;https://habr.com/ru/articles/112222/&quot;&gt;Структуры данных: двоичная куча (binary heap)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;🧑‍💻 &lt;strong&gt;Собеседования&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Интересный факт, что при прохождении собеседования на вашем языке программирования такая структура данных может отсутствовать.&lt;/p&gt;
&lt;p&gt;Например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В .NET 6 появилась встроенная реализация приоритетной очереди, она так и называется &lt;code&gt;PriorityQueue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;А вот в JavaScript из коробки в нет подобной реализации&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В таком случае можно быстро реализовать приоритетную очередь с помощью динамического массива:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Описать класс PriorityQueue, у которого под капотом используется динамический массив&lt;/li&gt;
&lt;li&gt;Метод Enqueue — добавляет элемент в конец динамического массива&lt;/li&gt;
&lt;li&gt;Метод Dequeue — извлекает элемент с наименьшим приоритетом&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Эта реализация, будет работать очень медленно, но нам нужна лишь эмитация приоритетной очереди, ведь нам главное решить задачу и показать, что мы понимаем принцип работы этой структуры данных. Но прежде чем, писать даже такую быструю реализацию, лучше согласовать свои действия с интервьюером.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;⌨️ Пример задачи с Leetcode&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Чтобы понять как и зачем использовать приоритетную очередь можно порешать следующие задачи на Leetcode&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/top-k-frequent-words/&quot;&gt;Top K Frequent Words&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/top-k-frequent-elements/&quot;&gt;Top K Frequent Elements&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Еще по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/skbkontur/articles/666018/&quot;&gt;.NET 6: PriorityQueue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cupg2TGIkyM&quot;&gt;Top K Frequent Words - Priority Queue Approach (LeetCode)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#algorithms #interview&lt;/p&gt;</content:encoded></item><item><title>📖 Примеры использования Chat GPT</title><link>https://cherkashin.dev/posts/114/</link><guid isPermaLink="true">https://cherkashin.dev/posts/114/</guid><description>📖 Примеры использования Chat GPT

Сегодня хочу поделиться статьей с шаблонами для ChatGPT, который поможет понять, как правильно формулировать запросы 10 шаблонов запросов для ChatGPT, которые выдадут качественные ответы в помощь продакт-менеджеру.

Автор делится шаблонами и рассказывает:

Как генерировать вопросы для...</description><pubDate>Fri, 21 Jul 2023 07:03:04 GMT</pubDate><content:encoded>&lt;p&gt;📖 **Примеры использования Chat GPT&lt;/p&gt;
&lt;p&gt;**Сегодня хочу поделиться статьей с шаблонами для ChatGPT, который поможет понять, как правильно формулировать запросы &lt;a href=&quot;https://habr.com/ru/companies/selectel/articles/741482/&quot;&gt;10 шаблонов запросов для ChatGPT, которые выдадут качественные ответы в помощь продакт-менеджеру.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Автор делится шаблонами и рассказывает:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Как генерировать вопросы для интервью&lt;/li&gt;
&lt;li&gt;Генерировать и валидировать идеи&lt;/li&gt;
&lt;li&gt;Составить план-презентации&lt;/li&gt;
&lt;li&gt;Писать SQL запросы&lt;/li&gt;
&lt;li&gt;Генерировать Excel и Google Sheet формулы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я сам почти каждый день использую Chat GPT. В прошлом месяце я, наконец-то, прошёл бесплатный курс от &lt;a href=&quot;https://practicum.yandex.ru/algorithms-interview/&quot;&gt;Яндекс.Практикума по подготовке к Алгоритмическому собеседованию&lt;/a&gt; и &lt;strong&gt;также не без помощи Chat GPT&lt;/strong&gt;. Я использовал его для:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Нахождения задач на Leetcode описанных в курсе, чтобы потренироваться прежде чем читать разбор решения. Chat GPT выдаёт название задачи (иногда даже вместе с ссылкой), которая появится первой в списке поиска гугла.&lt;/li&gt;
&lt;li&gt;Для перевода C++ и Python кода на JavaScript, ведь намного приятнее читать примеры кода на языке, который ты знаешь.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Также я использовал Chat GPT для генерации glob паттернов. Хотя в этом он оказался не так уже хорош.&lt;/p&gt;
&lt;p&gt;#fridayreading #chatgpt #algorithms #ai&lt;/p&gt;</content:encoded></item><item><title>Нужно выстраивать правила игры, добиваться их принятия и играть по ним</title><link>https://cherkashin.dev/posts/113/</link><guid isPermaLink="true">https://cherkashin.dev/posts/113/</guid><description>Нужно выстраивать правила игры, добиваться их принятия и играть по ним

В последнее время, когда я обсуждаю работу, часто использую фразу &quot;правила игры&quot;. Такие правила есть везде: в вашей команде, компании или политике.

🔄 Ситуация

Представим ситуацию: вам что-то не нравится в вашей работе (ну а вдруг). Например, ваш...</description><pubDate>Mon, 17 Jul 2023 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Нужно выстраивать правила игры, добиваться их принятия и играть по ним&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В последнее время, когда я обсуждаю работу, часто использую фразу “правила игры”. Такие правила есть везде: в вашей команде, компании или политике.&lt;/p&gt;
&lt;p&gt;🔄 &lt;strong&gt;Ситуация&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Представим ситуацию: вам что-то не нравится в вашей работе (ну а вдруг). Например, ваша команда не работает над техническим долгом в проекте, и кодовая база деградирует. К тому же вы не являетесь тимлидом, который может диктовать условия, просто взяв и заставив всех либо “делать хорошо”, либо начать планировать рефакторинг и устранение технического долга в новом спринте.&lt;/p&gt;
&lt;p&gt;В этом случае вы можете попробовать изменить те самые «правила игры». Если ваша идея понравится и её получится внедрить, то даже товарищи которые «выше вас на голову» должны будут следовать новым «правилам».&lt;/p&gt;
&lt;p&gt;✍️ &lt;strong&gt;Как?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Например, вы можете подготовить презентацию и попробовать убедить коллег, что работа над техническим долгом будет полезна как команде, так и бизнесу.
Но, конечно, далеко не факт, что ваше предложение будет с восторгом воспринято и утверждено. В этом случае, увы, “правила” изменить не удалось.&lt;/p&gt;
&lt;p&gt;☄️ &lt;strong&gt;Возвращение к договорённостям&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Часто бывает, что кто-то не следует правилам и всячески их игнорирует. В таком случае нужно “возвращаться к договорённостям”, напоминая о правилах. “Мол, помнишь, мы всей командой договорились, что будем придерживаться этого подхода? Если ты считаешь, что нам это не нужно, то подготовь аргументы и расскажи всей команде, почему этот подход плох, и мы должны перестать ему следовать”. Вряд ли кто-то захочет напрягаться, и проще будет следовать правилам.&lt;/p&gt;
&lt;p&gt;⚠️ Но все это будет работать только если ваша команда играете по правилам.&lt;/p&gt;
&lt;p&gt;🎭 &lt;strong&gt;Аналогия&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Эти правила можно рассматривать как законы в стране, по которым должны играть все граждане. Если тем или иным политическим группам что-то не нравится, они могут продвигать нужные им законы (не всегда хорошие), чтобы изменить правила игры.&lt;/p&gt;
&lt;p&gt;❌ &lt;strong&gt;Чего делать не стоит&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Многие, вместо того чтобы что-то сделать, просто жалуются из раза в раз. Иногда, чтобы привести таких людей в чувства, можно их спросить: “Окей, мы можем это изменить?” Если ничего изменить нельзя, то смысл жаловаться? Это только демотивирует, раздражает и никоим образом не влияет на те самые “правила игры”.&lt;/p&gt;
&lt;p&gt;——&lt;/p&gt;
&lt;p&gt;Кстати, о планировании технического долга я писал вот &lt;a href=&quot;https://t.me/cherkashindev/39&quot;&gt;тут&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#processes #technicaldebt&lt;/p&gt;</content:encoded></item><item><title>Как правильно “придираться” во время код ревью</title><link>https://cherkashin.dev/posts/112/</link><guid isPermaLink="true">https://cherkashin.dev/posts/112/</guid><description>Как правильно “придираться” во время код ревью

Когда вы проверяете код своего коллеги не нужно требовать от него “идеального” кода.

ℹ️ Правило такое: вам следует апрувить изменения, если они улучшают в целом кодовую базу, даже если они не идеальны, ведь идеального кода не существует. Код можно сделать лучше чем он бы...</description><pubDate>Wed, 12 Jul 2023 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Как правильно “придираться” во время код ревью&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда вы проверяете код своего коллеги не нужно требовать от него “идеального” кода.&lt;/p&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;Правило такое:&lt;/strong&gt; вам следует апрувить изменения, если они улучшают в целом кодовую базу, даже если они не идеальны, ведь идеального кода не существует. Код можно сделать лучше чем он был до этого, но не идеальным.&lt;/p&gt;
&lt;p&gt;Если вы увидели, какие-то небольшие помарки в коде, которые совершенно не критичны, то не нужно категорично требовать их исправления. Вы можете оставить комментарии, и оставить на усмотрение автора, необходимо ли вносить какие-то изменения.&lt;/p&gt;
&lt;p&gt;ℹ️ &lt;a href=&quot;https://google.github.io/eng-practices/review/reviewer/standard.html&quot;&gt;В стандартах код ревью гугла&lt;/a&gt;, описано, что в таких ситуациях можно использовать префикс &lt;strong&gt;NIT&lt;/strong&gt;, в комментариях к пул реквесту. &lt;strong&gt;NIT&lt;/strong&gt; — сокращение от “nitpick” или “придираться”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;❓В каких ситуациях стоит использовать NIT&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Чтобы выразить своё мнение или личное предпочтение. Очень важно отличать такие комментарии, от фактов. Довольно часто ревьюеры выставляют собственное мнение как истину и единственно верное решение&lt;/li&gt;
&lt;li&gt;Чтобы указать автору на мелкие замечания, которые не обязательно исправлять&lt;/li&gt;
&lt;li&gt;В целях обучения, когда вы менторите начинающего разработчика и ваш комментарий носит чисто образовательный характер&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Подробнее об этом можно почитать здесь:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://google.github.io/eng-practices/review/reviewer/standard.html&quot;&gt;The Standard of Code Review&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#codereview #fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​Проверка именования файлов и папок с помощью плагина eslint-plugin-import</title><link>https://cherkashin.dev/posts/110/</link><guid isPermaLink="true">https://cherkashin.dev/posts/110/</guid><description>​​Проверка именования файлов и папок с помощью плагина eslint-plugin-import

Во время код ревью, можно заметить, что мы часто оставляем одни и те же комментарии об именованиях или каких-то соглашениях (которые описаны в вики, и которые никто не читает). В такой момент, нужно задуматься можно ли эти проверки как-то опти...</description><pubDate>Mon, 10 Jul 2023 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/1a8b41f8c91f34aebe0b8.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Проверка именования файлов и папок с помощью плагина eslint-plugin-import&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Во время код ревью, можно заметить, что мы часто оставляем одни и те же комментарии об именованиях или каких-то соглашениях (которые описаны в вики, и которые никто не читает). В такой момент, нужно задуматься можно ли эти проверки как-то оптимизировать. Например недавно я писал пост &lt;a href=&quot;https://t.me/cherkashindev/92&quot;&gt;о том как контролировать импорты в JS с помощью import/no-restricted-path&lt;/a&gt;. Сегодня я хочу рассказать о проверке именования файлов и папок.&lt;/p&gt;
&lt;p&gt;Наверняка в вашем проекте есть какая-то определённая структура организации папок, например, это могут быть папки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/models&lt;/li&gt;
&lt;li&gt;/services&lt;/li&gt;
&lt;li&gt;/stores&lt;/li&gt;
&lt;li&gt;/pages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И скорее всего все файлы в этих папках должны иметь определённый суффикс:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Model&lt;/li&gt;
&lt;li&gt;Service&lt;/li&gt;
&lt;li&gt;Store&lt;/li&gt;
&lt;li&gt;Page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И уж точно, в каждом проекте есть утилитные файлы для строк, массивов или ваших внутренних бизнес моделей. И как такие файлы только не именуют:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Helper/Helpers&lt;/li&gt;
&lt;li&gt;Util/Utils&lt;/li&gt;
&lt;li&gt;Utility/Utilities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Чтобы избежать всей этой путаницы и обеспечить единое именование файлов можно использовать плагин &lt;code&gt;eslint-plugin-import&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Плагин содержит несколько плавил:&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;strong&gt;check-file/filename-blocklist&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Синтаксис следующий — вы описываете объект, у которого:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ключи — запрещённые паттерны&lt;/li&gt;
&lt;li&gt;значения — тот паттерн, который рекомендуется использовать.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Например, если мы хотим обеспечить единое именование утилитных методов, &lt;strong&gt;чтобы все они оканчивались на `Utils`&lt;/strong&gt;, то нам нужно запретить использование суффиксов: Helper, Util, Utilities. Также, нужно учесть, что:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Первая буква может быть как в верхнем, так и в нижнем регистрах&lt;/li&gt;
&lt;li&gt;Все суффиксы могут быть как в единственном, так и во множественном числе&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Описание такого правила будет выглядеть так:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;plugins&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;  &apos;check-file&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;rules&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &quot;check-file/filename-blocklist&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;error&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;    &quot;**/*+([Hh]elper?(s|*)|[Uu]til|[Uu]tilitie?(s|*)).ts&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;*Utils.ts&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;2️⃣ &lt;strong&gt;check-file/folder-naming-convention&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Это правило позволяет нам задать паттерн именования папок:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ключ — паттерн для папок, которые необходимо валидировать&lt;/li&gt;
&lt;li&gt;значение — паттерн, которому папки должны удовлетворять. В нашем случае, паттерну удовлетворяют все папки, которые не называются Helpers, Util, Utilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;check-file/folder-naming-convention&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;error&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;        &quot;src/**/&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;!([Hh]elper?(s|*)|[Uu]til|[Uu]tilitie?(s|*))&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Все правила описываются с помощью &lt;a href=&quot;https://en.wikipedia.org/wiki/Glob_%28programming&quot;&gt;glob-паттернов&lt;/a&gt;). Протестировать свой паттерн можно &lt;a href=&quot;https://globster.xyz/&quot;&gt;тут&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#linters #javascript #archtecture&lt;/p&gt;</content:encoded></item><item><title>📖 Why I’ve stopped exporting defaults from my JavaScript modules</title><link>https://cherkashin.dev/posts/109/</link><guid isPermaLink="true">https://cherkashin.dev/posts/109/</guid><description>📖 Why I’ve stopped exporting defaults from my JavaScript modules

Сегодня на повестке статья из далёкого и спокойного 2019 “Why I&apos;ve stopped exporting defaults from my JavaScript modules”.

В статье автор предлагает отказаться от экспортов по-умолчанию в JavaScript. Я бы выделил 2 причины, которые кажутся для меня наи...</description><pubDate>Fri, 07 Jul 2023 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Why I’ve stopped exporting defaults from my JavaScript modules&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня на повестке статья из далёкого и спокойного 2019 “&lt;a href=&quot;https://humanwhocodes.com/blog/2019/01/stop-using-default-exports-javascript-module/&quot;&gt;Why I’ve stopped exporting defaults from my JavaScript modules&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;В статье автор предлагает отказаться от экспортов по-умолчанию в JavaScript. Я бы выделил 2 причины, которые кажутся для меня наиболее важными:&lt;/p&gt;
&lt;p&gt;1️⃣ Дефолтные экспорты не указывают имя функции или класса, которую вы импортируете, что может (и будет) вызывать неконсистентность в именовании.&lt;/p&gt;
&lt;p&gt;В одном файле вы можете указать имя &lt;code&gt;LinkedList&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;import LinkedList from &quot;./linked-list.js&quot;;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;А в другом файле, другой разработчик может указать имя &lt;code&gt;List&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;import List from &quot;./linked-list.js&quot;;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;В случае с именованными экспортами, вы не можете просто присвоить рандомное имя, оно должно совпадать с именем экспортируемой функции/класса/объекта&lt;/p&gt;
&lt;p&gt;&lt;code&gt;import { LinkedList } from &quot;./linked-list.js&quot;;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;При этом, если в глобальном поиске вы напишите &lt;code&gt;LinkedList&lt;/code&gt; вы сможете без всяких проблем найти все использования этой переменной.&lt;/li&gt;
&lt;li&gt;При этом вы также просто сможете переименовать компонент во всей кодовой базе, потому что везде используется одно и тоже имя.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2️⃣ Когнитивная нагрузка замедляет разработку. Если вы используете дефолтные экспорты, вам придётся самостоятельно, каждый раз указывать название импорта. В случае с именованными экспортами ваша IDE наверняка подскажет вам имя, как только вы начнёте печатать и вам останется лишь нажать Enter.&lt;/p&gt;
&lt;p&gt;3️⃣ Если вы всегда используете именованные экспорты, вам больше не нужно выбирать между именованными и дефолтными экспортами. Например, если изначально в файле вы экспортировали только одну функцию и теперь вам нужно экспортировать ещё одну, вам не придётся заменить везде неименованные импорты на именованные.&lt;/p&gt;
&lt;p&gt;⚠️** Исключения**&lt;/p&gt;
&lt;p&gt;К сожалению, в некоторых ситуациях нельзя использовать именованные экспорты. Одним из примеров может служить &lt;code&gt;React.lazy(() ⇒ import(&apos;../path&apos;))&lt;/code&gt; используемый для &lt;a href=&quot;https://react.dev/reference/react/lazy#lazy&quot;&gt;код сплитинга и ленивой загрузки&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;🤖** ESlint**&lt;/p&gt;
&lt;p&gt;Чтобы убедиться, что все разработчики используют именованные экспорты, вы можете использовать правило &lt;a href=&quot;https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-default-export.md&quot;&gt;import/no-default-export&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Когда я добавлял это правило в наш проект, я наткнулся на &lt;a href=&quot;https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20&quot;&gt;GitLab issue&lt;/a&gt;, где команда Гитлаба планировали перейти с дефолтных экспортов на именованные. Они также ссылаются на эту статью.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://humanwhocodes.com/blog/2019/01/stop-using-default-exports-javascript-module/&quot;&gt;Оригинал на английском&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/devschacht/%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D1%8F-%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D1%82%D0%B0%D0%BB-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D1%8D%D0%BA%D1%81%D0%BF%D0%BE%D1%80%D1%82-%D0%BF%D0%BE-%D1%83%D0%BC%D0%BE%D0%BB%D1%87%D0%B0%D0%BD%D0%B8%D1%8E-%D0%B2-%D0%BC%D0%BE%D0%B8%D1%85-javascript-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8F%D1%85-d03e63bed126&quot;&gt;Перевод на русский&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#linters #eslint #javascript #architecture #fridayreading&lt;/p&gt;</content:encoded></item><item><title>В наше непростое время важно деверсифицировать не только источники доходов, но и социальные сети,…</title><link>https://cherkashin.dev/posts/108/</link><guid isPermaLink="true">https://cherkashin.dev/posts/108/</guid><description>В наше непростое время важно деверсифицировать не только источники доходов, но и социальные сети, когда заблокировать могут что угодно и когда угодно. Поэтому будет круто, если вы подпишитесь на меня на альтернативных площадках:

ХабрЯндекс ДзенВКПикабу

||Вам не сложно, а мне приятно 🙂
||
#about_me</description><pubDate>Mon, 03 Jul 2023 10:00:04 GMT</pubDate><content:encoded>&lt;p&gt;В наше непростое время важно деверсифицировать не только источники доходов, но и социальные сети, когда заблокировать могут что угодно и когда угодно. Поэтому будет круто, если вы подпишитесь на меня на альтернативных площадках:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/users/cherkalexander&quot;&gt;Хабр&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzen.ru/cherkashindev&quot;&gt;Яндекс Дзен&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vk.com/cherkashin_dev&quot;&gt;ВК&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pikabu.ru/@cherkalexander&quot;&gt;Пикабу&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;||Вам не сложно, а мне приятно 🙂
||
#about_me&lt;/p&gt;</content:encoded></item><item><title>📖 What developers need to know about Chrome&apos;s Memory and Energy Saver modes - Chrome Developers</title><link>https://cherkashin.dev/posts/107/</link><guid isPermaLink="true">https://cherkashin.dev/posts/107/</guid><description>📖 What developers need to know about Chrome&apos;s Memory and Energy Saver modes - Chrome Developers

В конце прошлого года в Google Chrome появились 2 новых режима

Memory Saver (Экономия памяти)Energy Saver (Энергосбережение)

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

🔸 Memory Sav...</description><pubDate>Fri, 30 Jun 2023 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;📖** What developers need to know about Chrome’s Memory and Energy Saver modes - Chrome Developers**&lt;/p&gt;
&lt;p&gt;В конце прошлого года в Google Chrome появились 2 новых режима&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Memory Saver (Экономия памяти)&lt;/li&gt;
&lt;li&gt;Energy Saver (Энергосбережение)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Они позволяют более гибко управлять использованием системных ресурсов браузером.&lt;/p&gt;
&lt;p&gt;🔸 Memory Saver: Этот режим автоматически освобождает неиспользуемые фоновые вкладки, чтобы освободить память для активных вкладок и других запущенных приложений. Но для сложных сайтов с интерактивностью это может привести к проблемам восстановления состояния страницы.&lt;/p&gt;
&lt;p&gt;🔸 Energy Saver: Режим Energy Saver позволяет браузеру снизить частоту обновления экрана для экономии заряда батареи. Обычно, для большинства сайтов, не требуется внесение изменений, но если вы используете JavaScript-анимации, имейте в виду, что они могут замедлиться.&lt;/p&gt;
&lt;p&gt;👉 Важно, чтобы веб-разработчики учитывали эти новые режимы и обеспечивали безупречный опыт для пользователей. &lt;strong&gt;Рекомендуется сохранять состояние пользователей при изменении их активности и обрабатывать перезагрузки страницы после удаления вкладок.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В данный момент нет никаких событий, которые будут запущены перед выгрузкой вкладки. &lt;a href=&quot;https://developer.chrome.com/blog/memory-and-energy-saver-mode/#best-practices-to-handle-tab-discards&quot;&gt;Рекомендуются следующие способы сохранения состояния&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Периодически, когда состояние изменяется&lt;/li&gt;
&lt;li&gt;Когда вы переходите на другую вкладку, по событию &lt;code&gt;visibilitychange&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;visibilitychange&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (document.visibilityState &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;hidden&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    storeState&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;💡 &lt;a href=&quot;https://developer.chrome.com/blog/memory-and-energy-saver-mode/#testing-your-site-in-memory-saver-mode&quot;&gt;Не забудьте протестировать свой сайт&lt;/a&gt; в этих режимах, чтобы убедиться, что все работает как задумано.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Для этого можно открыть в адресной строке &lt;code&gt;chrome://discards&lt;/code&gt; и для нужно вам вкладки использовать кнопку &lt;strong&gt;Urgent Discard.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Инструменты автоматического тестирования пока не помогут вам протестировать эти режимы с помощью автотестов. Но вы можете использовать простую перезагрузку страницы, она почти полностью идентична выгрузке вкладки. Разница лишь в том, что при выгрузке вкладки, события &lt;code&gt;beforeunload&lt;/code&gt;, &lt;code&gt;pagehide&lt;/code&gt;и &lt;code&gt;unload&lt;/code&gt; не будут вызваны.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/blog/memory-and-energy-saver-mode/&quot;&gt;Подробнее можно почитать в статье&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#javascript #browser #frontend #fridayreading&lt;/p&gt;</content:encoded></item><item><title>📖 О бизнес процессах и авторитаризме</title><link>https://cherkashin.dev/posts/106/</link><guid isPermaLink="true">https://cherkashin.dev/posts/106/</guid><description>📖 О бизнес процессах и авторитаризме

На майских праздниках я наконец-то дочитал книгу “Авторитарная Россия. Бегство от свободы, или Почему у нас не приживается демократия”.

В ней были достаточно интересные мысли, которые непроизвольно вызывали у меня ассоциации с бизнес-процессами в компаниях.

💡 Мысль

Когда в гос...</description><pubDate>Fri, 23 Jun 2023 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;О бизнес процессах и авторитаризме&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На майских праздниках я наконец-то дочитал книгу “&lt;a href=&quot;https://www.litres.ru/book/vladimir-gelman/avtoritarnaya-rossiya-begstvo-ot-svobody-ili-pochemu-u-nas-65950798/chitat-onlayn/&quot;&gt;Авторитарная Россия. Бегство от свободы, или Почему у нас не приживается демократия&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;В ней были достаточно интересные мысли, которые непроизвольно вызывали у меня ассоциации с бизнес-процессами в компаниях.&lt;/p&gt;
&lt;p&gt;💡 &lt;strong&gt;Мысль&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда в государстве творится полный хаус, экономика в ужасном состоянии и государственные институты работают, мягко сказать, не оптимально, лишь нанося вред государству, то, вероятно, на время (в лучшем случае) придётся чем-то пожертвовать, чтобы решить часть проблем. Например, демократией.&lt;/p&gt;
&lt;p&gt;Как указывает автор, “Авторитаризм может быть подобен швам или гипсовой повязке, которые на время позволяют срастись разорванным тканям и дают тем самым  травмированному организму время и шансы на то, чтобы укрепить свой потенциал для “выращивания ” новых правил игры”.&lt;/p&gt;
&lt;p&gt;То есть, государство тем или иным образом берёт все рычаги власти в свои руки и наводит порядок “жёсткой рукой”. Таким образом временно (опять же, в лучшем случае) происходит отклонение от демократии в сторону авторитаризма.&lt;/p&gt;
&lt;p&gt;💼 &lt;strong&gt;Ассоциации с бизнес-процессами в компании&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Мне кажется, государство, если очень сильно упрощать, — та же самая компания, просто масштабы совсем другие.&lt;/p&gt;
&lt;p&gt;Если в компании не настроены процессы, начальство не понимает, чем занимаются сотрудники, как выпускаются новые релизы — то одним из вариантов развития событий может быть “закручивание гаек”, когда руководство берёт максимум полномочий в свои руки и усиливает контроль за сотрудниками и процессами.&lt;/p&gt;
&lt;p&gt;👀 &lt;strong&gt;Пример&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Менеджер думает, что его подчинённые тратят время на что-то не то, и хочет убедиться, что каждая минута их времени приносит пользу. В этом случае, вас могут попросить трекать время или слать ежедневные отчёты.&lt;/p&gt;
&lt;p&gt;Также как и в политическом контексте это можно отразиться на настроениях общества/сотрудников и они могут уехать из страны/найти другую работу.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; Главное не слишком сильно закручивать гайки, иначе весь механизм разлетится вдребезги.&lt;/p&gt;
&lt;p&gt;#processes #book #politics #fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​❓Как восстановить удалённый коммит в Git?</title><link>https://cherkashin.dev/posts/105/</link><guid isPermaLink="true">https://cherkashin.dev/posts/105/</guid><description>​​❓Как восстановить удалённый коммит в Git?

На днях я писал базовый компонент выпадающего меню. Всё как обычно, закончил работу и закоммитил.

Потом понял, что закоммитил в мастер, а не в ветку с фичей. Поэтому сделал git reset --soft, чтобы удалить коммит, сохранив все изменённые файлы, и переключился в фича ветку.

...</description><pubDate>Mon, 19 Jun 2023 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/8081a43771f5fca5f33e7.jpg&quot;&gt;​​&lt;/a&gt;❓&lt;strong&gt;Как восстановить удалённый коммит в Git?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На днях я писал базовый компонент выпадающего меню. Всё как обычно, закончил работу и &lt;strong&gt;закоммитил&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Потом понял, что закоммитил в мастер, а не в ветку с фичей. Поэтому сделал &lt;code&gt;git reset --soft&lt;/code&gt;, чтобы удалить коммит, сохранив все изменённые файлы, и переключился в фича ветку.&lt;/p&gt;
&lt;p&gt;Если ветки сильно отличаются, то иногда приходится делать &lt;code&gt;git clean -fxd&lt;/code&gt;, чтобы удалить все ненужные артефакты. &lt;strong&gt;И тут я понял, что удалил все свои изменения.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Повезло, что перед этим я закоммитил свои изменения, хотя коммит и был удалён. Ведь git позволяет восстановить удалённые коммиты. Для этого я сделал:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git reflog&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Нашёл в списке хэш моего коммита и перенёс из него все изменения в текущую ветку с помощью: &lt;code&gt;git cherry-pick —no-commit &amp;#x3C;hash&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;#git&lt;/p&gt;</content:encoded></item><item><title>📖 Неделя после пуска или Cooldown week</title><link>https://cherkashin.dev/posts/104/</link><guid isPermaLink="true">https://cherkashin.dev/posts/104/</guid><description>📖 Неделя после пуска или Cooldown week

Как часто после очередного спринта вы чувствуете, что

в одном месте не успели отрефакторитьв другом месте не успели дописать документациюгде-то осталось пару багов, которые было бы неплохо пофикситьнужно рассказать команде о важных (или не очень) архитектурных изменениях или ба...</description><pubDate>Fri, 16 Jun 2023 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Неделя после пуска или Cooldown week&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Как часто после очередного спринта вы чувствуете, что&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;в одном месте не успели отрефакторить&lt;/li&gt;
&lt;li&gt;в другом месте не успели дописать документацию&lt;/li&gt;
&lt;li&gt;где-то осталось пару багов, которые было бы неплохо пофиксить&lt;/li&gt;
&lt;li&gt;нужно рассказать команде о важных (или не очень) архитектурных изменениях или базовых компонентах, которые были добавлены&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Кроме того, вам в любом случае нужно время между релизами, чтобы&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;подвести итог прошлого релиза&lt;/li&gt;
&lt;li&gt;запланировать следующий&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В этом случае вам подойдёт &lt;strong&gt;Cooldown Week&lt;/strong&gt; подход (Неделя после пуска), который поможет вам закрыть все недоделки (или, по крайней мере, самые важные из них), прежде чем погрузиться с головой в новый спринт.&lt;/p&gt;
&lt;p&gt;“Неделя после пуска” — это не какой-то набор обязательных активностей, вы можете применять её в своей компании под ваши собственные нужды.&lt;/p&gt;
&lt;p&gt;Такой подход используется в Basecamp и в Бюро Горбунова&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://basecamp.com/handbook/09-how-we-work#cooldown&quot;&gt;Basecamp — How we work — Cooldown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bureau.ru/soviet/20150709/&quot;&gt;Бюро Горбунова — Как оценивать доработки после запуска?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#processes #fridayreading #planning&lt;/p&gt;</content:encoded></item><item><title>🍎 Хочу поделиться Apple Shortcuts для добавления в инбокс Notion</title><link>https://cherkashin.dev/posts/103/</link><guid isPermaLink="true">https://cherkashin.dev/posts/103/</guid><description>🍎 Хочу поделиться Apple Shortcuts для добавления в инбокс Notion

Хочу поделиться с вами отличной находкой, связанной с Apple Shortcuts. Год назад я упоминал, что с  помощью Apple Shortcuts  можно с легкостью добавлять записи в базу ноутшена, например, я использую её для добавления записей в мой инбокс.

Недавно я пом...</description><pubDate>Mon, 12 Jun 2023 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;🍎** Хочу поделиться Apple Shortcuts для добавления в инбокс Notion**&lt;/p&gt;
&lt;p&gt;Хочу поделиться с вами отличной находкой, связанной с Apple Shortcuts. &lt;a href=&quot;https://t.me/cherkashindev/43&quot;&gt;Год назад я упоминал&lt;/a&gt;, что с  помощью Apple Shortcuts  можно с легкостью добавлять записи в базу ноутшена, например, я использую её для добавления записей в мой инбокс.&lt;/p&gt;
&lt;p&gt;Недавно я помогал настраивать систему управления проектами, &lt;a href=&quot;https://habr.com/ru/articles/696698/&quot;&gt;похожую на ту, которую я использую сам&lt;/a&gt;, и тогда я задался вопросом: можно ли поделиться уже созданным шорткатом, чтобы не настраивать всё по-новой? И оказалось, что это вполне возможно! Просто нужно расшарить ссылку (но предварительно удалить свой токен и идентификатор базы).&lt;/p&gt;
&lt;p&gt;Чтобы настроить это, вам нужно сделать всего лишь несколько шагов (скриншот в комментариях):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;В блоке “Text” вставьте идентификатор вашей базы вместо &quot;&lt;your data-base=&quot;&quot; id=&quot;&quot;&gt;&quot;.&lt;/your&gt;&lt;/li&gt;
&lt;li&gt;В блоке “Get contents of” вставьте ваш секретный токен интеграции вместо &quot;&lt;your secret=&quot;&quot; token=&quot;&quot;&gt;&quot;.&lt;/your&gt;&lt;/li&gt;
&lt;li&gt;Вместо “Name” укажите название вашего поля, если оно отличается.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Я подготовил два шаблона для добавления записей, чтобы вам было проще начать использовать это:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.icloud.com/shortcuts/f0132543a4634ca89d577448287ccd5a&quot;&gt;Команда для добавления записи текстом&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.icloud.com/shortcuts/407ef4d8cf5c4ebcb363d1a2ca86f517&quot;&gt;Команда для добавления записи голосом&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Инструкцию по настройке команды с нуля &lt;a href=&quot;https://www.youtube.com/watch?v=EHdBHn960Ms&amp;#x26;ab_channel=PolyNome&quot;&gt;можно найти здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Если будут вопросы — пишите, будем разбираться.&lt;/p&gt;
&lt;p&gt;#notion #nocode #automation&lt;/p&gt;</content:encoded></item><item><title>🎬 Backend-Driven UI</title><link>https://cherkashin.dev/posts/102/</link><guid isPermaLink="true">https://cherkashin.dev/posts/102/</guid><description>🎬 Backend-Driven UI

Сегодня посоветую доклад с HolyJS — Виталий Полещук, Стёпа Михайлюк — Server-driven UI в вебе. Не пиши, а описывай свой фронтeнд

Парни в докладе рассказывают, как можно не заниматься формошлёпством, точнее как его упростить, чтобы создавать новые формы можно было проще и быстрее.

Backend Driven ...</description><pubDate>Fri, 09 Jun 2023 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;🎬 &lt;strong&gt;Backend-Driven UI&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня посоветую доклад с HolyJS — &lt;a href=&quot;https://www.youtube.com/watch?v=s4KnMVP9KL4&amp;#x26;ab_channel=HolyJS&quot;&gt;Виталий Полещук, Стёпа Михайлюк — Server-driven UI в вебе. Не пиши, а описывай свой фронтeнд&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Парни в докладе рассказывают, как можно не заниматься формошлёпством, точнее как его упростить, чтобы создавать новые формы можно было проще и быстрее.&lt;/p&gt;
&lt;p&gt;Backend Driven UI представляет собой подход, в котором бэкенд говорит клиенту, как должен выглядеть интерфейс. В случае с формами, например, может передаваться массив элементов, где у каждого элемента есть тип:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;header&lt;/li&gt;
&lt;li&gt;select&lt;/li&gt;
&lt;li&gt;checkbox&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;клиент проходится по этому массиву и рендерит соответствующий UI компонент. Таким образом реализация компонентов находится на фронте, а их расположение и взаимодействие на бэке.&lt;/p&gt;
&lt;p&gt;👍 &lt;strong&gt;Основные преимущества Backend Driven UI&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Возможность делегировать создание форм бэкендерам или аналитикам&lt;/li&gt;
&lt;li&gt;Мгновенные релизы, достаточно обновить данные на сервере для изменения формы сразу на всех устройствах&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/yandex/articles/683886/&quot;&gt;Яндекс выпускает DivKit — фреймворк для server-driven UI с открытым кодом&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #frontend #architecture&lt;/p&gt;</content:encoded></item><item><title>🏃 Пару лет назад в качестве целей на год я добавил «пробежать полумарафон». Теперь наконец-то…</title><link>https://cherkashin.dev/posts/100/</link><guid isPermaLink="true">https://cherkashin.dev/posts/100/</guid><description>🏃 Пару лет назад в качестве целей на год я добавил «пробежать полумарафон». Теперь наконец-то можно вычеркнуть этот пункт из давно потерянного списка.</description><pubDate>Mon, 05 Jun 2023 07:08:58 GMT</pubDate><content:encoded>&lt;p&gt;🏃 Пару лет назад в качестве целей на год я добавил «пробежать полумарафон». Теперь наконец-то можно вычеркнуть этот пункт из давно потерянного списка.&lt;/p&gt;</content:encoded><media:content url="https://cherkashin.dev/telegram-media/msg-100-1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/telegram-media/msg-100-1.jpg"/></item><item><title>​​🧮 Задача на знание замыканий в JavaScript</title><link>https://cherkashin.dev/posts/98/</link><guid isPermaLink="true">https://cherkashin.dev/posts/98/</guid><description>​​🧮 Задача на знание замыканий в JavaScript

Если вам приходится собеседовать начинающих фронтендеров, то следующая простая задача поможет вам проверить, понимает ли разработчик принцип работы с замыканиями, и может ли он применять их на деле.

/
 Нужно написать функцию, которая принимает число N и возвращает функцию,...</description><pubDate>Mon, 22 May 2023 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/e6e86396fa84918c89646.jpg&quot;&gt;​​&lt;/a&gt;🧮** Задача на знание замыканий в JavaScript**&lt;/p&gt;
&lt;p&gt;Если вам приходится собеседовать начинающих фронтендеров, то следующая простая задача поможет вам проверить, понимает ли разработчик принцип работы с замыканиями, и может ли он применять их на деле.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/** 
* Нужно написать функцию, которая принимает число N и возвращает функцию,
* вызов которой первые N раз возвращает &apos;yes&apos;, а потом – &apos;no&apos;.
*/
function canGetCount(n) {
    // code here
}

const getOne = canGetCount(2);
 
getOne()  === &apos;yes&apos;
getOne()  === &apos;yes&apos;
getOne()  === &apos;no&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#javascript #interview&lt;/p&gt;</content:encoded></item><item><title>📖 Выравнивание последнего элемента по правому краю с помощью flexbox</title><link>https://cherkashin.dev/posts/97/</link><guid isPermaLink="true">https://cherkashin.dev/posts/97/</guid><description>📖 Выравнивание последнего элемента по правому краю с помощью flexbox

Сегодня хочу порекомендовать короткую, но очень полезную статью о флексбоксах How to Align Last Flex Item to Right.

Довольно часто необходимо сверстать UI, в котором все элементы выровнены слева, и только один необходимо выравнять по правому краю.
...</description><pubDate>Fri, 19 May 2023 08:00:03 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Выравнивание последнего элемента по правому краю с помощью flexbox&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня хочу порекомендовать короткую, но очень полезную статью о флексбоксах &lt;a href=&quot;https://medium.com/@iamryanyu/how-to-align-last-flex-item-to-right-73512e4e5912&quot;&gt;How to Align Last Flex Item to Right&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Довольно часто необходимо сверстать UI, в котором все элементы выровнены слева, и только один необходимо выравнять по правому краю.&lt;/p&gt;
&lt;p&gt;Раньше я делал так:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Создавал 2 div’а-обёртки&lt;/li&gt;
&lt;li&gt;Всё что должно быть слева клал в левый &lt;code&gt;div&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Элемент, который должен быть справа, клал в правый &lt;code&gt;div&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;К родительскому элементу применял &lt;code&gt;justify-content: space-between&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это решение всегда работает, но можно обойтись и без div’ов-обёрток. Всё, что нужно сделать — применить &lt;code&gt;margin-left: auto&lt;/code&gt; к элементу, который должен располагаться справа.&lt;/p&gt;
&lt;p&gt;Вот простой пример разметки из трех элементов и соответствующий CSS-код, где последний элемент выравнивается по правому краю.&lt;/p&gt;
&lt;p&gt;HTML разметка:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;html&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;flex-container&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;flex-item&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Первый элемент&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;flex-item&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Второй элемент&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;flex-item align-right&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;Последний элемент&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;CSS код:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.flex-container&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    display&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;flex&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.flex-item&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    border&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; solid&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; black&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.align-right&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;    margin-left&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;auto&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;💡 &lt;strong&gt;Пояснение&lt;/strong&gt;
Дело в том, что всё свободное пространство будет распределено между auto-маржинами.  Подробнее можно почитать в спеке флексбоксов &lt;a href=&quot;https://www.w3.org/TR/css-flexbox-1/#auto-margins&quot;&gt;Aligning with auto margins&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#html #css #flexbox #fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​🧮 Задача на знание this в JavaScript</title><link>https://cherkashin.dev/posts/96/</link><guid isPermaLink="true">https://cherkashin.dev/posts/96/</guid><description>​​🧮 Задача на знание this в JavaScript

Иногда на собеседованиях дают подобные каверзные задачи, в которых необходимо хорошо понимать, как работают одновременно: стрелочные функции, контекст this и замыкания. Вот одна из задач, которую мне давали на собеседовании пару лет назад.

Что будет выведено в консоль?

functio...</description><pubDate>Mon, 24 Apr 2023 10:00:02 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/6195ca41f629ea30c1ccf.jpg&quot;&gt;​​&lt;/a&gt;🧮 &lt;strong&gt;Задача на знание this в JavaScript&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Иногда на собеседованиях дают подобные каверзные задачи, в которых необходимо хорошо понимать, как работают одновременно: стрелочные функции, контекст &lt;code&gt;this&lt;/code&gt; и замыкания. Вот одна из задач, которую мне давали на собеседовании пару лет назад.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Что будет выведено в консоль?&lt;/strong&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;js&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    x: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    bar&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: () &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.x),&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;    baz&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      console.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;.x);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;foo.x &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; 50&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; obj1&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;obj1.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;bar&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ?&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;obj1.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;baz&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ?&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; obj2&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; foo.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;call&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;({ x: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; obj2.bar;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ?&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;obj2.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;bar&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ?&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;obj2.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;baz&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Необходимая теория для решения задачи&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;this&lt;/code&gt; - контекст вызова функции. Если метод вызывается не на объекте, то &lt;code&gt;this&lt;/code&gt; — глобальный объект &lt;code&gt;window&lt;/code&gt;, иначе &lt;code&gt;this&lt;/code&gt; указывает на объект, на котором был вызван метод.&lt;/li&gt;
&lt;li&gt;У стрелочной функции нет собственного &lt;code&gt;this&lt;/code&gt;. Если внутри стрелочной функции идёт обращение к &lt;code&gt;this&lt;/code&gt;, его значение, как и обычная переменная, берётся из внешнего лексического окружения.&lt;/li&gt;
&lt;li&gt;Если метод объекта присвоить переменной, и вызвать такую переменную-функцию, то контекст потеряется и &lt;code&gt;this&lt;/code&gt; будет ссылаться на &lt;code&gt;window&lt;/code&gt;. Но это не работает в случае стрелочной функции, так как у неё нет собственного &lt;code&gt;this&lt;/code&gt;, поэтому и потерять она его не может.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Разбор задачи построчно&lt;/strong&gt;
6. &lt;code&gt;bar&lt;/code&gt; — стрелочная функция, &lt;code&gt;this&lt;/code&gt; берётся из лексического окружения
7. &lt;code&gt;baz&lt;/code&gt; — обычная функция, поэтому &lt;code&gt;this&lt;/code&gt; будет ссылаться на возвращаемый объект
15. Так как функция &lt;code&gt;foo&lt;/code&gt; вызывается не на объекте, то &lt;code&gt;this&lt;/code&gt; в этом случае равен глобальному объекту — &lt;code&gt;window&lt;/code&gt;.
16. Так как стрелочная функция берёт this из лексического окружения, то &lt;code&gt;this&lt;/code&gt; = &lt;code&gt;window&lt;/code&gt;. В консоль будет выведен &lt;code&gt;undefined&lt;/code&gt;, потому что на &lt;code&gt;window&lt;/code&gt; не определено свойство &lt;code&gt;x&lt;/code&gt;.
17. Функция &lt;code&gt;baz&lt;/code&gt; реализована с помощью обычной функции, поэтому в данном случае &lt;code&gt;this&lt;/code&gt; ссылается на сам объект. В консоль будет выведено 20.
19. Здесь явно указывается контекст вызова функции — объект &lt;code&gt;{ x: 30 }&lt;/code&gt;
20-21. Так как метод &lt;code&gt;bar&lt;/code&gt; реализован с помощью стрелочной функции, то контекст в данном случае &lt;a href=&quot;https://learn.javascript.ru/bind#poterya-this&quot;&gt;не теряется&lt;/a&gt;. Используется контекст из лексического окружения — &lt;code&gt;{ x: 30 }&lt;/code&gt;. В консоль будет выведено 30.
22. Вызывается тот же метод &lt;code&gt;bar&lt;/code&gt;, логика точно такая же. В консоль будет выведено 30.
23. Явное указание контекста при вызову функции &lt;code&gt;foo&lt;/code&gt; никак не влияет на функцию &lt;code&gt;baz&lt;/code&gt;, так как метод вызывается на объекте, и контекстом будет являться данный объект. В консоль будет выведено 20.&lt;/p&gt;
&lt;p&gt;**Ответ **⬇️
undefined
20
30
30
20&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Теория по теме&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.javascript.ru/arrow-functions&quot;&gt;Повторяем стрелочные функции&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.javascript.ru/constructor-new&quot;&gt;Конструктор, оператор “new”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.javascript.ru/object-methods&quot;&gt;Методы объекта, “this”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.javascript.ru/bind&quot;&gt;Привязка контекста к функции&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#javascript #interview&lt;/p&gt;</content:encoded></item><item><title>​​📖 Процесс ревью кода структурно порочен. Вот, как его исправить</title><link>https://cherkashin.dev/posts/95/</link><guid isPermaLink="true">https://cherkashin.dev/posts/95/</guid><description>​​📖 Процесс ревью кода структурно порочен. Вот, как его исправить

На ревью слишком много времени тратится на переключение контекста и ожидание  автора и ревьера:

После создания PR’а, мы ждём, когда ревьюер закончит свои дела и изучит код автора.Если необходимо внести изменения, то приходится ждать, когда вернется ав...</description><pubDate>Fri, 21 Apr 2023 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/de2fc81c58a451759d7ad.jpg&quot;&gt;​​&lt;/a&gt;📖 &lt;a href=&quot;https://habr.com/ru/post/706252/&quot;&gt;Процесс ревью кода структурно порочен. Вот, как его исправить&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;На ревью слишком много времени тратится на переключение контекста и ожидание  автора и ревьера:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;После создания PR’а, мы &lt;strong&gt;ждём&lt;/strong&gt;, когда ревьюер закончит свои дела и изучит код автора.&lt;/li&gt;
&lt;li&gt;Если необходимо внести изменения, то &lt;strong&gt;приходится ждать&lt;/strong&gt;, когда вернется автор и внесет изменения, ведь скорее всего он уже занимается следующей задачей.&lt;/li&gt;
&lt;li&gt;И всё повторяется снова до тех пор, пока качество не удовлетворит ревьюера.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Часто ревьюер — более опытный коллега и  он знает, какие подходы лучше использовать и как нужно делать.  Высока вероятность, что автору будет необходимо внести изменения, так как его видение отличается от видения ревьюера.&lt;/p&gt;
&lt;p&gt;Поэтому нужно начинать ревью еще до того как PR готов, чтобы вероятность переделывания задачи была как можно ниже. Чем раньше произойдёт ревью — тем меньше будут отличаться видения, меньше изменений будет необходимо внести, и тем быстрее работа будет завершена.&lt;/p&gt;
&lt;p&gt;К тому же, если весь код уже готов и работает, и автор потратил много часов на его реализацию, какова вероятность, что вы попросите его вносить изменения? Слишком жалко потраченного времени.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Как решить?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Обсудить план решения с более опытным коллегой, чтобы в дальнейшем пришлось меньше переделывать&lt;/li&gt;
&lt;li&gt;Произвести первое ревью, когда изменения готовы на 30-50%. Скорее всего ваш план не сработал на 100%, поэтому ваши видения с ревьюером снова разошлись, поэтому нужно снова провести ревью. Здесь необходимо смотреть на концепцию решения задачи и не придираться к небольшим ошибкам.&lt;/li&gt;
&lt;li&gt;Чтобы сократить время ожидания ревьера можно ввести роль дежурного по ревью. Как только появляется PR, ревьер сразу же приступает к ревью. В свободное время ревьюер занимается низкоприоритетными задачами: техническим долгом или неважными багами.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Конечно, подход с дежурным сработает не в любой команде. Если проект и команда очень большие, то такой подход вряд ли подойдёт, ведь ни один человек в команде не будет полностью разбираться как реализован продукт и просто не сможет провести качественное ревью.&lt;/p&gt;
&lt;p&gt;#fridayreading #codereview&lt;/p&gt;</content:encoded></item><item><title>​​📖 Я наконец-то попробовал ChatGPT</title><link>https://cherkashin.dev/posts/94/</link><guid isPermaLink="true">https://cherkashin.dev/posts/94/</guid><description>​​📖 Я наконец-то попробовал ChatGPT

Я не особо успеваю за трендами, поэтому попробовать ChatGPT дошли руки только сейчас.

Регистрировался по инструкции из статьи.

Перед регистрацией почистил куки браузераВ качестве VPN использовал VeePN-расширение для хромаДля регистрации использовал свой google аккаунтПользовался ...</description><pubDate>Fri, 14 Apr 2023 10:00:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/71ad7b0035e574186dbd8.jpg&quot;&gt;​​&lt;/a&gt;📖 &lt;strong&gt;Я наконец-то попробовал ChatGPT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Я не особо успеваю за трендами, поэтому попробовать ChatGPT дошли руки только сейчас.&lt;/p&gt;
&lt;p&gt;Регистрировался по &lt;a href=&quot;https://habr.com/ru/post/704600/&quot;&gt;инструкции из статьи&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Перед регистрацией почистил куки браузера&lt;/li&gt;
&lt;li&gt;В качестве VPN использовал &lt;a href=&quot;https://chrome.google.com/webstore/detail/free-vpn-for-chrome-vpn-p/majdfhpaihoncoakbjgbdhglocklcgno?hl=en&quot;&gt;VeePN-расширение&lt;/a&gt; для хрома&lt;/li&gt;
&lt;li&gt;Для регистрации использовал свой google аккаунт&lt;/li&gt;
&lt;li&gt;Пользовался сервисом &lt;a href=&quot;https://onlinesim.io/&quot;&gt;OnlineSim&lt;/a&gt; для регистрации иностранного номера чтобы получить SMS код для регистрации&lt;/li&gt;
&lt;li&gt;Пополнил счёт на 50 рублей через СБП&lt;/li&gt;
&lt;li&gt;Пользовался Нидерландским номером для регистрации, который купил за $0.54&lt;/li&gt;
&lt;li&gt;Без VPN не могу зайти на сайт ChatGPT&lt;/li&gt;
&lt;li&gt;Переодически нужно перезагружать страницу&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я попросил его написать пост на основе текста, который вы прочитали выше и вот что получилось&lt;/p&gt;
&lt;p&gt;#chatgpt #fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​Контроль импортов с помощью import/no-restricted-paths</title><link>https://cherkashin.dev/posts/92/</link><guid isPermaLink="true">https://cherkashin.dev/posts/92/</guid><description>​​Контроль импортов с помощью import/no-restricted-paths

Когда мы задумываемся о структуре проекта — то мы подразумеваем некоторое разделение на области/модули, где каждый модуль имеет свою зону ответственности. Помимо этого, зачастую, один модуль не должен ничего знать о другом, иными словами, ему запрещается импорти...</description><pubDate>Tue, 11 Apr 2023 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/10a8d5fe0f44b8050f71f.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Контроль импортов с помощью import/no-restricted-paths&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда мы задумываемся о структуре проекта — то мы подразумеваем некоторое разделение на области/модули, где каждый модуль имеет свою зону ответственности. Помимо этого, зачастую, один модуль не должен ничего знать о другом, иными словами, ему запрещается импортировать что-либо из другого модуля.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пример 1️⃣&lt;/strong&gt;
Допустим у нас есть:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ui-kit&lt;/code&gt; — папка с базовыми компонентами&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rest-api&lt;/code&gt; — папка с сервисами для коммуникации с сервером
Очевидно, что содержимое &lt;code&gt;rest-api&lt;/code&gt; не должно ничего знать о компонентах.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Пример 2️⃣&lt;/strong&gt;
Теперь представим, что у нас есть 2 папки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;components&lt;/code&gt; — базовые компоненты, кнопки, инпуты, …&lt;/li&gt;
&lt;li&gt;&lt;code&gt;domains&lt;/code&gt; — реализация фичей, например форма логина
В этом случае содержимое &lt;code&gt;domains&lt;/code&gt; может использовать любые компоненты из &lt;code&gt;components&lt;/code&gt;, но не наоборот. Если мы хотим использовать компонент из &lt;code&gt;domains&lt;/code&gt; в &lt;code&gt;components&lt;/code&gt;, правильнее будет перенести его также в &lt;code&gt;components&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Решение&lt;/strong&gt; ✅
Eslint предоставляет мощное правило &lt;a href=&quot;https://github.com/import-js/eslint-plugin-import&quot;&gt;import/no-restricted-paths&lt;/a&gt;, которое поможет описать зависимости между папками/модулями и запретить нежелательные импорты, описанные в примерах.&lt;/p&gt;
&lt;p&gt;Если вы используете &lt;a href=&quot;https://create-react-app.dev/&quot;&gt;CRA&lt;/a&gt; вам достаточно добавить следующий код в &lt;code&gt;package.json&lt;/code&gt; в поле &lt;code&gt;eslintConfig&lt;/code&gt;. В примере ниже мы запрещаем любые импорты из папки &lt;code&gt;domains&lt;/code&gt; в папку &lt;code&gt;components&lt;/code&gt; из примера 2.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;  &quot;import/no-restricted-paths&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;    &quot;error&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;zones&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;          &quot;target&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;./src/components&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;          &quot;from&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;./src/domains&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;settings&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;  &quot;import/resolver&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;    &quot;node&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;      &quot;extensions&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;        &quot;.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;        &quot;.jsx&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;} &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Если вы используете TypeScript, дополнительно нужно установить пакет &lt;a href=&quot;https://github.com/import-js/eslint-import-resolver-typescript&quot;&gt;eslint-import-resolver-typescript&lt;/a&gt; и изменить поле &lt;code&gt;settings&lt;/code&gt; следующим образом:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;json&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;settings&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;    &quot;import/resolver&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;      &quot;typescript&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#8DDB8C&quot;&gt;        &quot;project&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;./tsconfig.json&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  } &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Подробнее можено почитать в статье &lt;a href=&quot;https://habr.com/ru/companies/okko/articles/716042/&quot;&gt;Как правила линтинга влияют на архитектуру приложения&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#linters #javascript #typescript #architecture&lt;/p&gt;</content:encoded></item><item><title>📖 React 18 — useTransition, useDeferredValue</title><link>https://cherkashin.dev/posts/91/</link><guid isPermaLink="true">https://cherkashin.dev/posts/91/</guid><description>📖 React 18 — useTransition, useDeferredValue

React 18 вышел уже почти год назад, но только сейчас решил поискать наглядные примеры использования новых хуков useTransition и useDeferredValue и наткнулся на отличное видео “Новые хуки useTransition и useDeferredValue в React 18”. Оба хука работают благодаря конкурентном...</description><pubDate>Fri, 07 Apr 2023 10:00:03 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;React 18 — useTransition, useDeferredValue&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;React 18 вышел уже почти год назад, но только сейчас решил поискать наглядные примеры использования новых хуков &lt;code&gt;useTransition&lt;/code&gt; и &lt;code&gt;useDeferredValue&lt;/code&gt; и наткнулся на отличное видео “&lt;a href=&quot;https://www.youtube.com/watch?v=QfIwLDy8j_U&amp;#x26;ab_channel=%D0%9C%D0%B8%D1%85%D0%B0%D0%B8%D0%BB%D0%9D%D0%B5%D0%BF%D0%BE%D0%BC%D0%BD%D1%8F%D1%89%D0%B8%D0%B9&quot;&gt;Новые хуки useTransition и useDeferredValue в React 18&lt;/a&gt;”. Оба хука работают благодаря конкурентному режиму, который позволяет прерывать рендеринг.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пример&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Допустим у нас есть поле поиска и очень длинный список заказов. При каждом изменении мы ре-рендерим список. Например, вы хотите купить новый айфон и вводите &lt;strong&gt;iphone&lt;/strong&gt; в поле поиска, ре-рендеринг произойдёт 6 раз (для значений i, ip, iph ipho, iphon, iphone) — на каждое изменение. К тому же пока рендеринг не завершён — основной поток приложения заблокирован и пользователь не может взаимодействовать с приложением, из-за чего страдает UX.  Однако это очень не оптимально, ведь когда мы вводим каждый новый символ, предыдущие результаты поиска для нас больше неактуальны и было бы логичнее приостановить рендеринг и запустить новый.&lt;/p&gt;
&lt;p&gt;Именно эту проблему решают новые хуки, они позволяют приостановить или отменить запущенный рендеринг, если есть более важное событие, например, ввод пользователя.&lt;/p&gt;
&lt;p&gt;Вероятно вы не замечаете проблем с производительностью на своём Macbook Pro M2, но далеко не у всех пользователей такие же шустрые устройства. Но вы можете стать ближе к народу и включить эмуляцию медленной производительности в DevTools в Performance ⇒ CPU ⇒ 6x slowdown.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;useDeferredValue&lt;/code&gt; не содержит конкретного таймаута, для обновления значения. Реакт сам решит, когда значение будет обновлено в зависимости от от того, насколько Реакт в данный момент занят другими вычислениями.  Принцип работы хука довольно простой, когда &lt;code&gt;useDeferredValue&lt;/code&gt; получает новое значение — под капотом запускается ре-рендер, если этот ре-рендер не прерван — UI обновляется. Но если хук получил ещё одно новое значение — то старое состояние устарело, вычисление виртуального дома прерывается и процесс начинается заново.&lt;/p&gt;
&lt;p&gt;Принцип работы работы &lt;code&gt;useTransition&lt;/code&gt;  аналогичен — если &lt;code&gt;startTransition&lt;/code&gt; запускается несколько раз — отрендерится лишь последний результат, а все предыдущие будут прерваны.&lt;/p&gt;
&lt;p&gt;Оба хука взаимозаменяемы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Используйте &lt;code&gt;useTransition&lt;/code&gt;, если у вас есть доступ к обновлению состояния&lt;/li&gt;
&lt;li&gt;Используйте &lt;code&gt;useDeferredValue&lt;/code&gt;, например, если вам необходимо запустить обновление в ответ на изменение пропса.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Подход похож на &lt;code&gt;debounce&lt;/code&gt;, но это не одно и то же. Когда мы используем &lt;code&gt;debounce&lt;/code&gt;, рендер просто откладывается, но мы не можем его прервать, и UI всё равно может зависнуть через указанный таймаут.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/companies/domclick/articles/689152/&quot;&gt;Основные изменения React 18&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/reference/react/useDeferredValue#how-does-deferring-a-value-work-under-the-hood&quot;&gt;useDeferredValue — How does deferring a value work under the hood?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/reference/react/useTransition&quot;&gt;useTransition&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #react #javascript #frontend&lt;/p&gt;</content:encoded></item><item><title>▶️ Интегрируем Яндекс Музыку в Visual Studio Code</title><link>https://cherkashin.dev/posts/90/</link><guid isPermaLink="true">https://cherkashin.dev/posts/90/</guid><description>▶️ Интегрируем Яндекс Музыку в Visual Studio Code

3 года назад я начал писать расширение для Яндекс Музыки, за это время пришлось решить много интересных задач:

1️⃣ Создание библиотеки для Яндекс.Музыки
2️⃣ Создание OpenAPI схемы и обход CORS
3️⃣ Воспроизведение музыки с помощью Electron
4️⃣ Ну и собственно интеграци...</description><pubDate>Mon, 03 Apr 2023 09:00:03 GMT</pubDate><content:encoded>&lt;p&gt;▶️ &lt;strong&gt;Интегрируем Яндекс Музыку в Visual Studio Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;3 года назад я начал писать расширение для Яндекс Музыки, за это время пришлось решить много интересных задач:&lt;/p&gt;
&lt;p&gt;1️⃣ Создание библиотеки для Яндекс.Музыки
2️⃣ Создание OpenAPI схемы и обход CORS
3️⃣ Воспроизведение музыки с помощью Electron
4️⃣ Ну и собственно интеграция всего этого в VS Code&lt;/p&gt;
&lt;p&gt;Я наконец-то решил описать все трудности, с которыми я столкнулся, в статье на хабре. Поэтому переходим и скорее читаем.&lt;/p&gt;
&lt;p&gt;➡️ &lt;a href=&quot;https://habr.com/ru/post/725460/&quot;&gt;Интегрируем Яндекс Музыку в Visual Studio Code&lt;/a&gt; ⬅️&lt;/p&gt;
&lt;p&gt;#yandexmusic #vscode #javascript #openapi&lt;/p&gt;</content:encoded></item><item><title>Интегрируем Яндекс Музыку в Visual Studio Code</title><link>https://cherkashin.dev/articles/yandex-music-integration-vscode/</link><guid isPermaLink="true">https://cherkashin.dev/articles/yandex-music-integration-vscode/</guid><description>Представьте, что вы можете слушать свои любимые песни на Яндекс.Музыке, прямо из своего любимого редактора кода, не переключаясь между приложениями. Это уже не мечта, а реальность! В этой статье мы рассмотрим, как интегрировать Яндекс.Музыку в Visual Studio Code и наслаждаться любимой музыкой прямо во время работы.</description><pubDate>Sun, 02 Apr 2023 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/yandex-music-integration-vscode/image1.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/yandex-music-integration-vscode/image1.png"/></item><item><title>​​📖 Avoid These Common Pitfalls Of React useState</title><link>https://cherkashin.dev/posts/89/</link><guid isPermaLink="true">https://cherkashin.dev/posts/89/</guid><description>​​📖 Avoid These Common Pitfalls Of React useState

Статья описывает самые популярные ошибки при использовании useState в Реакте:

Избыточное состояние (Redundant State)Дублирующее состояние (Duplicate State)Обновление состояния через useEffect (Updating State Via useEffect)Подписка на изменения состояния через useEffe...</description><pubDate>Fri, 17 Mar 2023 10:00:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/c54c908c7318819340523.jpg&quot;&gt;​​&lt;/a&gt;📖 &lt;a href=&quot;https://profy.dev/article/react-usestate-pitfalls&quot;&gt;Avoid These Common Pitfalls Of React useState&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Статья описывает самые популярные ошибки при использовании &lt;code&gt;useState&lt;/code&gt; в Реакте:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Избыточное состояние (Redundant State)&lt;/li&gt;
&lt;li&gt;Дублирующее состояние (Duplicate State)&lt;/li&gt;
&lt;li&gt;Обновление состояния через useEffect (Updating State Via useEffect)&lt;/li&gt;
&lt;li&gt;Подписка на изменения состояния через useEffect (Listening To State Changes Via useEffect)&lt;/li&gt;
&lt;li&gt;Конфликтующие состояния (Contradicting State)&lt;/li&gt;
&lt;li&gt;Состояние с глубокой вложенностью (Deeply Nested State)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Среди описанные проблем нашёл практически кусок своего кода, связанный с асинхронными запросами — &lt;strong&gt;пример как не надо делать прикреплён&lt;/strong&gt;. Чтобы не совершать таких ошибок, нужно вспомнить о некоторых рекомендациях, когда лучше использовать &lt;code&gt;useReducer&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://reactjs.org/docs/hooks-reference.html#functional-updates:~:text=be%20skipped%20completely.-,Note,-Unlike%20the%20setState&quot;&gt;Для управления объектом, лучше использовать useReducer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Для управления состояниями, зависящими друг от друга, лучше использовать useReducer — как раз этот случай и описывается в статье&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#react #frontend #fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​📖 Не трогайте разработчиков. Отстаньте. Просто не беспокойте</title><link>https://cherkashin.dev/posts/88/</link><guid isPermaLink="true">https://cherkashin.dev/posts/88/</guid><description>​​📖 Не трогайте разработчиков. Отстаньте. Просто не беспокойте

Статья описывает настройку процессов таким образом, чтобы по минимуму отвлекать разработчиков. Для этого назначается дежурный, который отдувается за всех. Например, у  вас есть команда поддержки, которая постоянно дергает разработчиков, когда не может спр...</description><pubDate>Fri, 10 Mar 2023 10:00:08 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/8acb85d273a9aff6185f5.jpg&quot;&gt;​​&lt;/a&gt;📖 **Не трогайте разработчиков. Отстаньте. Просто не беспокойте
**
Статья описывает настройку процессов таким образом, чтобы по минимуму отвлекать разработчиков. Для этого назначается дежурный, который отдувается за всех. Например, у  вас есть команда поддержки, которая постоянно дергает разработчиков, когда не может справиться самостоятельно. Можно назначить дежурного — именно этого человека и будут дергать, а он будет стараться решить проблему самостоятельно, и дергать команду только в крайнем случае, таким образом остальные могут быть сконцентрированы на своих задачах.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Возможные обязанности дежурного:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Защищать команду, чтобы её никто не отвлекал лишними вопросам или созвонами&lt;/li&gt;
&lt;li&gt;Менеджер обращается к дежурному, заказчики также ходят с вопросами к дежурному&lt;/li&gt;
&lt;li&gt;Следить за метриками&lt;/li&gt;
&lt;li&gt;Писать постмортемы&lt;/li&gt;
&lt;li&gt;Проверять написанную документацию за разработчиками&lt;/li&gt;
&lt;li&gt;Следить, чтобы не было повторяющейся работы. Если вам часто нужно делать одно и тоже, то дежурный это всё запишет и составит задачи на автоматизацию&lt;/li&gt;
&lt;li&gt;Выкатывать релизы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Плюсы:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Дежурный погружается в специфику работы команды и продукт более глубоко&lt;/li&gt;
&lt;li&gt;Снижается нагрузка на команду и она может спокойно заниматься своими задачами&lt;/li&gt;
&lt;li&gt;Дежурства помогают навести порядок там, куда обычно не доходят руки. Зачастую &lt;strong&gt;дежурный делает то, что должен разработчик, но ему всегда некогда.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Смена деятельности&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Особенности процесса&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Кажется что производительность команды снизится, но на самом деле этого не должно произойти — ведь остальные будут сосредоточены на решении задач и будут более продуктивны&lt;/li&gt;
&lt;li&gt;Дежурят только желающие, никого не заставляют&lt;/li&gt;
&lt;li&gt;Для обучения можно назначать двух дежурных, один — опытный, второй — новичок. Опытный ничего не делает руками, кроме ЧП ситуаций, так происходит обучение новичка.&lt;/li&gt;
&lt;li&gt;Может быть несколько дежурных: кто-то отвечает за релизы, кто-то за поддержку&lt;/li&gt;
&lt;li&gt;У дежурного не должно быть релизных задач, если у него появляется свободное время:
&lt;ul&gt;
&lt;li&gt;Он дописывает документацию&lt;/li&gt;
&lt;li&gt;Работает над техническим долгом&lt;/li&gt;
&lt;li&gt;Автоматизирует бизнес процессы&lt;/li&gt;
&lt;li&gt;Фиксит баги&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Как начать вводить&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Выписать всё, что может отвлекать&lt;/li&gt;
&lt;li&gt;Начать автоматизировать то, что можно
&lt;ul&gt;
&lt;li&gt;Создание метрик&lt;/li&gt;
&lt;li&gt;Релизы&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;На релиз другой уменьшить количество продуктовых задач и заняться автоматизацией и внутренними инструментами, чтобы увеличить продуктивность команды в будущем&lt;/li&gt;
&lt;li&gt;Начать вводить дежурства с опытным наставником&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/company/gazprombank/blog/678000/&quot;&gt;https://habr.com/ru/company/gazprombank/blog/678000/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading  #processes&lt;/p&gt;</content:encoded></item><item><title>📖 Мигрируем БД в продакшене без даунтайма</title><link>https://cherkashin.dev/posts/87/</link><guid isPermaLink="true">https://cherkashin.dev/posts/87/</guid><description>📖 Мигрируем БД в продакшене без даунтайма

Основной совет, который даётся в статье — нужно разбивать деплой новой фичи на 2 и более части, чтобы соблюсти обратную совместимость. Это очень важно, если для выкатки новой фичи необходимо изменить схему базы данных.

Обратная совместимость необходима, потому что во время д...</description><pubDate>Fri, 03 Mar 2023 10:00:13 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Мигрируем БД в продакшене без даунтайма&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Основной совет, который даётся в статье — нужно разбивать деплой новой фичи на 2 и более части, чтобы соблюсти обратную совместимость. Это очень важно, если для выкатки новой фичи необходимо изменить схему базы данных.&lt;/p&gt;
&lt;p&gt;Обратная совместимость необходима, потому что во время деплоя в кластере будут одновременно инстансы со старой версий и обновлённой версией приложения, и нам необходимо обеспечить их одновременную бесперебойную работу.&lt;/p&gt;
&lt;p&gt;Например, если требуется удалить поле из БД, нужно выполнять деплой в 2 захода:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Удаляем весь код, работающий с этим столбцом — деплоим&lt;/li&gt;
&lt;li&gt;Удаляем столбец и снова  — деплоим&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Если бы мы удаляли одновременно поле и код, взаимодействующий с кодом, то мы бы столкнулись с ситуацией, когда старые версии, всё ещё будут пытаться обращаться к этому полю, но так как поле удалено — это может привести к даунтайму.&lt;/p&gt;
&lt;p&gt;В нашем случае, такой ситуации не случится, так как к моменту удаления столбца, все инстансы в кластере обновлены и больше не взаимодействуют с полем, теперь его можно удалить.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/664028/&quot;&gt;https://habr.com/ru/post/664028/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #architecture&lt;/p&gt;</content:encoded></item><item><title>​​📄 Офлайн-режим в Google Docs и Notion</title><link>https://cherkashin.dev/posts/86/</link><guid isPermaLink="true">https://cherkashin.dev/posts/86/</guid><description>​​📄 Офлайн-режим в Google Docs и Notion

В прошлом году на майских праздниках я ездил в Нижний Новгород, и в дороге мне было необходимо написать документ по работе. Как известно, в поезде интернета нет практически никакого. Поэтому сперва я решил составить документ локально, а потом перенести в гугл документы, чтобы п...</description><pubDate>Mon, 27 Feb 2023 10:00:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/8d6c3188bdcc8f290293d.jpg&quot;&gt;​​&lt;/a&gt;📄 &lt;strong&gt;Офлайн-режим в Google Docs и Notion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В прошлом году на майских праздниках я ездил в Нижний Новгород, и в дороге мне было необходимо написать документ по работе. Как известно, в поезде интернета нет практически никакого. Поэтому сперва я решил составить документ локально, а потом перенести в гугл документы, чтобы поделиться с коллегами. Но я вспомнил об &lt;strong&gt;офлайн-режиме в гугл документах&lt;/strong&gt; и решил его протестировать.&lt;/p&gt;
&lt;p&gt;Честно говоря, я был в восторге. Когда появилась сеть я открыл нужный мне документ и активировал офлайн режим &lt;strong&gt;(File ⇒ Make available offline)&lt;/strong&gt;. После этого вы можете просто работать над своим документом, и как только появится интернет все изменения будут сохранены в облаке, а до тех пор все изменения будут храниться локально. Офлайн-режим также доступен в Google Sheets и Google Slides.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://notionzen.com/notion-offline/&quot;&gt;Команда Notion также работает над офлайн-режимом&lt;/a&gt;. Он работает примерно так же как и в гугл документах - необходимо просто открыть страницу и не закрывать её, после этого вы можете свободно работать над документом, как только появится интернет — все изменения будут сохранены.&lt;/p&gt;
&lt;p&gt;#notion #googledocs #documentation&lt;/p&gt;</content:encoded></item><item><title>​​🎨 Первый дизайн в Figma</title><link>https://cherkashin.dev/posts/85/</link><guid isPermaLink="true">https://cherkashin.dev/posts/85/</guid><description>​​🎨 Первый дизайн в Figma

Нарисовал небольшую обложку для расширения Я.Музыки. Всё оказалось гораздо проще, чем я думал.
Ссылки, которые использовал при создании дизайна:

1️⃣ Gradients in Figma
2️⃣ Guide to components in Figma

#design #figma #yandexmusic #vscode</description><pubDate>Thu, 23 Feb 2023 08:48:14 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/ed32efb760e44b40fdac4.png&quot;&gt;​​&lt;/a&gt;🎨 &lt;strong&gt;Первый дизайн в Figma&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Нарисовал небольшую обложку для &lt;a href=&quot;https://github.com/acherkashin/yandex-music-extension&quot;&gt;расширения Я.Музыки&lt;/a&gt;. Всё оказалось гораздо проще, чем я думал.
Ссылки, которые использовал при создании дизайна:&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;a href=&quot;https://designcode.io/figma-handbook-gradients&quot;&gt;Gradients in Figma&lt;/a&gt;
2️⃣ &lt;a href=&quot;https://help.figma.com/hc/en-us/articles/360038662654-Guide-to-components-in-Figma&quot;&gt;Guide to components in Figma&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#design #figma #yandexmusic #vscode&lt;/p&gt;</content:encoded></item><item><title>​​🎨 Excalidraw — сервис для рисования диаграмм</title><link>https://cherkashin.dev/posts/84/</link><guid isPermaLink="true">https://cherkashin.dev/posts/84/</guid><description>​​🎨 Excalidraw — сервис для рисования диаграмм

На днях узнал о классном сервисе для рисования диаграмм

В бесплатной версии можно работать лишь на одном холсте, но его можно сохранить локально и таким образом работать над несколькими диаграммамиДоступные разные стили оформления текста, мне очень нравится рукописныйМо...</description><pubDate>Mon, 20 Feb 2023 10:00:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/6f1daab439a5202e5e26d.jpg&quot;&gt;​​&lt;/a&gt;🎨 &lt;strong&gt;Excalidraw — сервис для рисования диаграмм&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На днях узнал о классном сервисе для рисования диаграмм&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В бесплатной версии можно работать лишь на одном холсте, но его можно сохранить локально и таким образом работать над несколькими диаграммами&lt;/li&gt;
&lt;li&gt;Доступные разные стили оформления текста, мне очень нравится рукописный&lt;/li&gt;
&lt;li&gt;Можно использовать сторонние &lt;a href=&quot;https://libraries.excalidraw.com/?target=_excalidraw&amp;#x26;referrer=https%3A%2F%2Fexcalidraw.com%2F&amp;#x26;useHash=true&amp;#x26;token=noUrOID7ZLK5jAKRu3tMB&amp;#x26;theme=light&amp;#x26;version=2&amp;#x26;sort=default&quot;&gt;библиотеки компонентов&lt;/a&gt;, например, чтобы рисовать UML диаграммы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#tools #documentation #digrams&lt;/p&gt;</content:encoded></item><item><title>​​📖 Как платформа управления знаниями упрощает онбординг — TEAMLY</title><link>https://cherkashin.dev/posts/83/</link><guid isPermaLink="true">https://cherkashin.dev/posts/83/</guid><description>​​📖 Как платформа управления знаниями упрощает онбординг — TEAMLY

Недавно решил разобраться как правильно проводить онбординг в компании и написал об этом пару постов:
1️⃣ Система онбординга комфорт-класса
2️⃣ Матрица компетенций

Но, я решил пойти немного дальше и порефлексировать над своим опытом онбординга. Подума...</description><pubDate>Fri, 17 Feb 2023 13:44:26 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/718c9c05afb386ddbb170.jpg&quot;&gt;​​&lt;/a&gt;📖 &lt;a href=&quot;https://vc.ru/services/599329-kak-platforma-upravleniya-znaniyami-uproshchaet-onbording-teamly&quot;&gt;Как платформа управления знаниями упрощает онбординг — TEAMLY&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Недавно решил разобраться как правильно проводить онбординг в компании и написал об этом пару постов:
1️⃣ &lt;a href=&quot;https://t.me/cherkashindev/77&quot;&gt;Система онбординга комфорт-класса&lt;/a&gt;
2️⃣ &lt;a href=&quot;https://t.me/cherkashindev/71&quot;&gt;Матрица компетенций&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Но, я решил пойти немного дальше и порефлексировать над своим опытом онбординга. Подумать о том, как можно было бы его провести, а также найти инструмент, который может в этом помочь.&lt;/p&gt;
&lt;p&gt;Раньше я скорее всего выбрал бы Notion, но в текущих обстоятельствам не очень надёжно класть все яйца в одну корзину, особенно если корзина имеет возможность блокировать пользователей из-за санкций. Поэтому решил посмотреть на аналоги на Российском рынке и наткнулся на TEAMLY — отечественную платформу для совместной работы и управления знаниями.&lt;/p&gt;
&lt;p&gt;Всё это вылилось в статью &lt;a href=&quot;https://vc.ru/services/599329-kak-platforma-upravleniya-znaniyami-uproshchaet-onbording-teamly&quot;&gt;Как платформа управления знаниями упрощает онбординг — TEAMLY&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Статья расскажет:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;как проходили мои онбординги&lt;/li&gt;
&lt;li&gt;зачем нужен качественный онбординг и кому он выгоден&lt;/li&gt;
&lt;li&gt;как правильно провести онбординг&lt;/li&gt;
&lt;li&gt;как TEAMLY может помочь в проведении онбординга&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #processes #onboarding&lt;/p&gt;</content:encoded></item><item><title>​​⚙️ Автоматизация Code Review — DangerJs</title><link>https://cherkashin.dev/posts/82/</link><guid isPermaLink="true">https://cherkashin.dev/posts/82/</guid><description>​​⚙️ Автоматизация Code Review — DangerJs

Некоторое время назад, я осознал, что бОльшую часть времени во время Code Review, я трачу совсем не на то, чтобы проверить, что задача выполнена корректно. БОльшая часть времени уходит, чтобы убедиться, что разработчики следуют правилам, стандартам и договорённостям.

Многие п...</description><pubDate>Mon, 13 Feb 2023 10:00:12 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/1047f0996323d9f80edc9.jpg&quot;&gt;​​&lt;/a&gt;⚙️** Автоматизация Code Review — DangerJs**&lt;/p&gt;
&lt;p&gt;Некоторое время назад, я осознал, что бОльшую часть времени во время Code Review, я трачу совсем не на то, чтобы проверить, что задача выполнена корректно. БОльшая часть времени уходит, чтобы убедиться, что разработчики следуют правилам, стандартам и договорённостям.&lt;/p&gt;
&lt;p&gt;Многие проблемы можно решить с помощью линтеров:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://eslint.org/&quot;&gt;Eslint для JS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/StyleCop/StyleCop&quot;&gt;StyleCop для C#&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Многие, но к сожалению не все, и в этом случае можно попробовать использовать Danger.
Danger — это такой линтер, который позволяет нам описывать наши правила с помощью &lt;a href=&quot;https://github.com/danger/danger-js&quot;&gt;JS&lt;/a&gt;, &lt;a href=&quot;https://github.com/danger/danger&quot;&gt;Ruby&lt;/a&gt;, &lt;a href=&quot;https://github.com/danger/swift&quot;&gt;Swift&lt;/a&gt;, &lt;a href=&quot;https://danger.systems/python/&quot;&gt;Python&lt;/a&gt; или &lt;a href=&quot;https://danger.systems/kotlin/&quot;&gt;Kotlin&lt;/a&gt;. Я использую &lt;a href=&quot;https://danger.systems/js/&quot;&gt;DangerJS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Примеры&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/orta/danger-plugin-spellcheck&quot;&gt;Проверка опечаток в *.md файлах&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/macklinu/danger-plugin-no-test-shortcuts&quot;&gt;Проверка использования `test.skip`&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/revathskumar/danger-plugin-npm-audit&quot;&gt;Проверка npm пакеты на наличие уязвимостей&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/BearAlliance/danger-plugin-artifact-size&quot;&gt;Генерация размера JS-бандла&lt;/a&gt;
Больше примеров можно посмотреть &lt;a href=&quot;https://danger.systems/js/#:~:text=WHAT%20DOES%20THIS%20LOOK%20LIKE%3F&quot;&gt;здесь&lt;/a&gt;, а  список уже реализованных правил в виде плагинов можно посмотреть &lt;a href=&quot;https://github.com/danger/awesome-danger&quot;&gt;здесь&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Преимущества&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Чем быстрее вы получите фидбэк — тем лучше. То как быстро отработает Danger, зависит лишь от конфигурации вашего CI, в отличие от вашего коллеги, его не нужно ждать, пока он доделает свои задачи.&lt;/li&gt;
&lt;li&gt;Также применение Danger может положительно сказаться на отношениях в коллективе. Вас не будет раздражать тот умник, который указывает вам, что вы опять что-то сделали не так.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Как понять что автоматизировать?&lt;/strong&gt;
Самый простой пример — понаблюдать за собой во время код ревью, какие комментарии вы обычно оставляете? Какие ошибки допускаете вы и ваши коллеги? Можно составить список повторяющихся проблем и попробовать их автоматизировать с помощью DangerJS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://danger.systems/js/guides/getting_started.html&quot;&gt;Getting started with DangerJs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@ivan.ha/integrate-danger-js-in-5-minutes-55515bc5355d&quot;&gt;Integrate Danger JS in 5 Minutes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javascript.plainenglish.io/automate-common-pull-request-feedback-with-danger-js-and-github-actions-a09a27ec01c9&quot;&gt;Automate common pull request feedback with Danger.js and Github Actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#codereview #tools&lt;/p&gt;</content:encoded></item><item><title>​​Технотекст 2022: шорт-листы по номинациям</title><link>https://cherkashin.dev/posts/81/</link><guid isPermaLink="true">https://cherkashin.dev/posts/81/</guid><description>​​Технотекст 2022: шорт-листы по номинациям

Вчера Хабр опубликовал список лучших статей отправленных на Технотекс. Рекомендую посмотреть — там довольно много интересного. К сожалению, моя статья в список не попала(

https://habr.com/ru/company/habr/blog/715670/

#fridayreading #habr</description><pubDate>Sat, 11 Feb 2023 14:39:27 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/39a0618e25fe8cc02fde5.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Технотекст 2022: шорт-листы по номинациям&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Вчера Хабр опубликовал список лучших статей отправленных на Технотекс. Рекомендую посмотреть — там довольно много интересного. К сожалению, &lt;a href=&quot;https://habr.com/ru/post/696698/&quot;&gt;моя статья&lt;/a&gt; в список не попала(&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/company/habr/blog/715670/&quot;&gt;https://habr.com/ru/company/habr/blog/715670/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #habr&lt;/p&gt;</content:encoded></item><item><title>💭✍️ Мышление письмом</title><link>https://cherkashin.dev/posts/80/</link><guid isPermaLink="true">https://cherkashin.dev/posts/80/</guid><description>💭✍️ Мышление письмом

Сам того не подозревая в прошлом году я начал практиковать мышление письмом. Я перестал сразу бросаться писать код, вместо этого, в начале я записываю свои мысли и обдумываю задачу. Во время решения сложных задач я выписываю все свои мысли, а при реализации большой фичи стараюсь составить план и ...</description><pubDate>Fri, 03 Feb 2023 08:26:25 GMT</pubDate><content:encoded>&lt;p&gt;💭✍️ &lt;strong&gt;Мышление письмом&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сам того не подозревая в прошлом году я начал практиковать &lt;a href=&quot;https://habr.com/ru/post/526336/&quot;&gt;мышление письмом&lt;/a&gt;. Я перестал сразу бросаться писать код, вместо этого, в начале я записываю свои мысли и обдумываю задачу. Во время решения сложных задач я выписываю все свои мысли, а при реализации большой фичи стараюсь составить план и описать принцип её работы. Всё это очень упрощает реализацию.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Зачем?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;По закону Миллера мы не можем держать в голове более 7-ми элементов&lt;/li&gt;
&lt;li&gt;Задача нашего мозга — генерация идей, а не запоминание. Лучше записывать идеи и обдумывать их пока они не ускользнули от вас&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Примеры применения:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если вы описываете свои мысли, то вы сможете проще писать документацию в проектах. Ведь большая часть уже готова — необходимо лишь немного причесать&lt;/li&gt;
&lt;li&gt;При решении задачи, просто накидывайте все идеи и начинайте их письменно продумывать. Если всё это делать в голове — вам мозг просто закипит и вы забудете почему те или иные варианты плохи, а какие хороши&lt;/li&gt;
&lt;li&gt;В дальнейшем вы сможете обосновать почему вы приняли то или иное решение&lt;/li&gt;
&lt;li&gt;Ведение проектов в Notion — мышление письмом, ведь при создании проекта всё &lt;strong&gt;записывается&lt;/strong&gt; в систему. Не нужно запоминать план действий — он зафиксирован, вы его не забудете&lt;/li&gt;
&lt;li&gt;Ведение блога — тоже мышление письмом. Ведь при написании поста вы записываете все свои мысли, а в дальнейшем сможете к ним вернуться.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Статья также расскажет, как данный подход:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Может улучшить психологическое состояние&lt;/li&gt;
&lt;li&gt;Используется в Amazon&lt;/li&gt;
&lt;li&gt;Используется для исследовательских задач&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/526336/&quot;&gt;https://habr.com/ru/post/526336/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​Индикаторы прогресса в Notion</title><link>https://cherkashin.dev/posts/79/</link><guid isPermaLink="true">https://cherkashin.dev/posts/79/</guid><description>​​Индикаторы прогресса в Notion

Наконец-то дошли руки добавить прогресс бар в свои проекты в Notion. Шаблон тоже обновил. Если хотите так же - вам сюда.

#notion</description><pubDate>Wed, 01 Feb 2023 06:00:09 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/c83f53614e28c20320ad2.png&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Индикаторы прогресса в Notion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Наконец-то дошли руки добавить прогресс бар в свои проекты в Notion. &lt;a href=&quot;https://www.notion.so/3ec14cd2c1194e10811d101d7cec6d99&quot;&gt;Шаблон&lt;/a&gt; тоже обновил. Если хотите так же - вам &lt;a href=&quot;https://t.me/marianotion/97&quot;&gt;сюда&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#notion&lt;/p&gt;</content:encoded></item><item><title>​​Проект &quot;Феникс&quot;</title><link>https://cherkashin.dev/posts/78/</link><guid isPermaLink="true">https://cherkashin.dev/posts/78/</guid><description>​​Проект &quot;Феникс&quot;

На новогодних праздниках я наконец-то прочитал Проект “Феникс”. Рекомендую к прочтению, если в вашей компании всё происходит хаотично, вечные авралы и сотни незавершенных фич, которые переносятся из релиза в релиз. В книге раскрываются следующие моменты:

Для чего необходим таск трекер и какие пробле...</description><pubDate>Fri, 27 Jan 2023 06:00:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/1d06d20f526ef1546b445.jpg&quot;&gt;​​&lt;/a&gt;**Проект “Феникс”
**
На новогодних праздниках я наконец-то прочитал Проект “Феникс”. Рекомендую к прочтению, если в вашей компании всё происходит хаотично, вечные авралы и сотни незавершенных фич, которые переносятся из релиза в релиз. В книге раскрываются следующие моменты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Для чего необходим таск трекер и какие проблемы он решает — все изменения должны отслеживаться, чтобы можно было понять, какие изменения приводят к сбою.&lt;/li&gt;
&lt;li&gt;Не нужно помечать все задачи как “срочные”, иначе не будет понятно над чем именно необходимо работать.&lt;/li&gt;
&lt;li&gt;Необходимо увеличивать производительность в узких местах — система работает настолько быстро, насколько работает самое медленное её звено. Если у вас есть сотрудник, на котором многое завязано, необходимо как можно сильнее разгрузить его и обучить других сотрудников.&lt;/li&gt;
&lt;li&gt;Если у вас постоянные авралы — возможно вам необходимо поставить часть ваших проектов “на паузу” и сосредоточиться на наиболее критических, которые наиболее важны. Если в вашем продукте слишком много багов — необходимо сосредоточиться на его стабилизации.&lt;/li&gt;
&lt;li&gt;Возможно даже стоит запустить новые проекты, которые помогут заранее выявить проблемы, до того как они будет замечена пользователями, например, внедрить систему мониторинга. Это поможет снижать объем “незапланированной работы”.&lt;/li&gt;
&lt;li&gt;Необходимо выплачивать свой “технический дол”, иначе в дальнейшем придётся тратить слишком много времени на выплату процентов в виде незапланированной работы.&lt;/li&gt;
&lt;li&gt;Не стоит загружать сотрудников на 100% при планировании, ведь по ходу работы будут появляться новые задачи — “незапланированная работа”, и у сотрудника не будет времени их решить. “Время ожидания — это “процент занятого времени”, разделённый на “процент свободного”“.&lt;/li&gt;
&lt;li&gt;Если ваша команда перегружена нужно уметь говорить “нет” новой работе.&lt;/li&gt;
&lt;li&gt;Если вы человек, который устанавливает правила — вам следует самому играть по этим правилам, иначе никто этого делать не будет.&lt;/li&gt;
&lt;li&gt;Как CI/CD может ускорить разработку, почему важно релизиться как можно чаще. Например, чтобы быстро выкатывать баг фиксы.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.litres.ru/book/proekt-feniks-roman-o-tom-kak-devops-menyaet-biznes-k-luchshemu-11083697/&quot;&gt;https://www.litres.ru/book/proekt-feniks-roman-o-tom-kak-devops-menyaet-biznes-k-luchshemu-11083697/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #book&lt;/p&gt;</content:encoded></item><item><title>Система онбординга комфорт-класса</title><link>https://cherkashin.dev/posts/77/</link><guid isPermaLink="true">https://cherkashin.dev/posts/77/</guid><description>Система онбординга комфорт-класса

Цель хорошего онбординга — получить максимум производительности от сотрудника в короткий срок. Это не значит, что из сотрудника нужно выжать всё до последней капли, онбординг должен проходить максимально комфортно с минимумом стресса.

⁉️ Почему онбординг — это очень важный процесс?

...</description><pubDate>Fri, 20 Jan 2023 06:00:03 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Система онбординга комфорт-класса&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Цель хорошего онбординга — получить максимум производительности от сотрудника в короткий срок. Это не значит, что из сотрудника нужно выжать всё до последней капли, онбординг должен проходить максимально комфортно с минимумом стресса.&lt;/p&gt;
&lt;p&gt;⁉️ &lt;strong&gt;Почему онбординг — это очень важный процесс?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Онбординг — это первое с чем сталкивается новый сотрудник, поэтому его оценка компании напрямую зависит от онбординга.&lt;/li&gt;
&lt;li&gt;При плохом онбординге сотрудник долго выходит на желаемую производительность. В то время как при хорошем онбординге, сотрудник мог бы принести больше пользы за те же деньги.&lt;/li&gt;
&lt;li&gt;При плохом онбординге, старшие разработчики вынуждены постоянно отвлекаться и вкладываться в развитие нового сотрудника, вместо решения задач.&lt;/li&gt;
&lt;li&gt;Ну и в конце концов, просто морально сложно, когда тебе приходится разбираться во всём самому, когда тебе ничего не рассказали, не показали, не объяснили. Это очень демотивирует, и компания рискует потерять сотрудника на самом старте.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;👍 &lt;strong&gt;Хороший онбординг выгоден всем&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сотрудник быстрее приносит реальную пользу компании, тратит меньше времени, сил и нервов&lt;/li&gt;
&lt;li&gt;Бизнес тратит меньше денег на выход специалиста на нужную производительность&lt;/li&gt;
&lt;li&gt;Работники меньше тратят времени на онбординг и занимаются решением бизнес задач&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🏁 &lt;strong&gt;Как начать&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Вы можете написать базовую документацию, по которой будет происходить онбординг&lt;/li&gt;
&lt;li&gt;Можно протестировать инструкцию на товарище по команде&lt;/li&gt;
&lt;li&gt;Во время онбординга нового сотрудника, вы протестируете инструкцию, внесёте коррективы и сможете использовать её в будущем постоянно улучшая&lt;/li&gt;
&lt;li&gt;Перед увольнением сотрудники могут писать документацию для их зоны ответственности&lt;/li&gt;
&lt;li&gt;Необходимо подготавливать вводные задачи для нового сотрудника&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🕵️‍♂️ &lt;strong&gt;Кто проводит онбординг&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Онбординг на уровне компании должен проводиться HR-отделом&lt;/li&gt;
&lt;li&gt;Локальный онбординг в команду, необязательно проводится тимлидом, но именно тимлид должен настроить этот процесс. Сам онбординг он может делегировать кому-нибудь из команды.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📖 &lt;strong&gt;Что должно быть в онбординге&lt;/strong&gt;
Скорее всего в каждой команде набор инструкций будет разным, например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Основные процессы в команде
&lt;ul&gt;
&lt;li&gt;Когда у вас проходят стендапы, в каком формате&lt;/li&gt;
&lt;li&gt;По каким дням демо, как его проводить&lt;/li&gt;
&lt;li&gt;Код ревью&lt;/li&gt;
&lt;li&gt;Планирование технического долга&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Проекты
&lt;ul&gt;
&lt;li&gt;Настройка и запуск проекта&lt;/li&gt;
&lt;li&gt;Технологии&lt;/li&gt;
&lt;li&gt;Архитектура&lt;/li&gt;
&lt;li&gt;Гайдлайны&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Как общаться с заказчиками&lt;/li&gt;
&lt;li&gt;Ожидания от разработчика&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=7zrRzELnr8U&amp;#x26;ab_channel=ManagementChannel&quot;&gt;https://www.youtube.com/watch?v=7zrRzELnr8U&amp;#x26;ab_channel=ManagementChannel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #processes&lt;/p&gt;</content:encoded></item><item><title>Задачи на собеседовании JavaScript разработчика</title><link>https://cherkashin.dev/posts/76/</link><guid isPermaLink="true">https://cherkashin.dev/posts/76/</guid><description>Задачи на собеседовании JavaScript разработчика

Напишите функция вычисления последовательности фибоначи

function fib(n) {
  // TODO: implement
}

fib(5); // [0, 1, 1, 2, 3]
fib(7); // [0, 1, 1, 2, 3, 5, 8]
fib(11);// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Напишите функцию, которая будет проверять на “глубокое” равенс...</description><pubDate>Mon, 16 Jan 2023 06:00:07 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Задачи на собеседовании JavaScript разработчика&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Напишите функция вычисления последовательности фибоначи&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;
function fib(n) {
  // TODO: implement
}

fib(5); // [0, 1, 1, 2, 3]
fib(7); // [0, 1, 1, 2, 3, 5, 8]
fib(11);// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Напишите функцию, которая будет проверять на “глубокое” равенство 2 входящих параметра&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;
function deepEqual(a, b) {
  // TODO: implement
}

const source = {a: 1, b: {c: 1}}

const test1 = {a: 1, b: {c: 1}}
const test2 = {a: 1, b: {c: 2}}
const test3 = {a: 1, c: {b: 1}}
const test4 = {a: 1, c: 2}
const test5 = {c: 2, a: 1}
const test6 = {a: 1, b: {c: {d: 5}}}

console.log(deepEqual(source, test1)) // -&gt; true
console.log(deepEqual(source, test2)) // -&gt; false
console.log(deepEqual(source, test3)) // -&gt; false
console.log(deepEqual(source, test4)) // -&gt; false
console.log(deepEqual(source, test5)) // -&gt; false
console.log(deepEqual(source, test6)) // -&gt; false
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Напишите функцию, которая принимает два аргумента:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Массив из ЦЕЛЫХ ПОЛОЖИТЕЛЬНЫХ ЧИСЕЛ и сумму в виде целого числа.&lt;/li&gt;
&lt;li&gt;Функция должна вернуть все ПОДПОСЛЕДОВАТЕЛЬНОСТИ чисел массива из аргумента, сумма которых равна числу, которое приходит вторым аргументом.&lt;/li&gt;
&lt;li&gt;Если решения нет, вернуть пустой массив.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;function findSum(array, targetSum) {
    //TODO: implement
}

array = [1, 5, 4, 1, 11, 1, 10, 9, 1, 9, 6, 4, 10]
targetSum = 10

findSum(array, targetSum)
// [ [ 1, 5, 4 ], [ 5, 4, 1 ], [ 10 ], [ 9, 1 ], [ 1, 9 ], [ 6, 4 ], [ 10 ]]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#interview #coding #interview_questions&lt;/p&gt;</content:encoded></item><item><title>​​Yandex Music Client for JavaScript</title><link>https://cherkashin.dev/posts/75/</link><guid isPermaLink="true">https://cherkashin.dev/posts/75/</guid><description>​​Yandex Music Client for JavaScript

За последние пару дней новогодних праздников я, наконец-то, сделал то, что собирался сделать пару лет - сгенерировал JavaScript-клиент для Яндекс.Музыки на основе OpenAPI-схемы.
Что это значит? Берётся OpenAPI-схема и скармливается генератору, на основе которой генерируется библиот...</description><pubDate>Mon, 09 Jan 2023 06:00:13 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/07aec6c0d624e44f156fa.jpg&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Yandex Music Client for JavaScript&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;За последние пару дней новогодних праздников я, наконец-то, сделал то, что собирался сделать пару лет - сгенерировал JavaScript-клиент для Яндекс.Музыки на основе &lt;a href=&quot;https://github.com/acherkashin/yandex-music-open-api&quot;&gt;OpenAPI-схемы&lt;/a&gt;.
Что это значит? Берётся OpenAPI-схема и скармливается генератору, на основе которой генерируется библиотека на определённом языке программирования, которая может использоваться для отправки запросов на сервер.&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://github.com/acherkashin/yandex-music-open-api/blob/main/src/yandex-music.yaml&quot;&gt;Описание OpenAPI-схемы на GitHub&lt;/a&gt;
👉 Для генерации клиента используется &lt;a href=&quot;https://www.npmjs.com/package/openapi-typescript-codegen&quot;&gt;openapi-typescript-codegen&lt;/a&gt;
👉 &lt;a href=&quot;https://www.npmjs.com/package/yandex-music-client&quot;&gt;JavaScript-клиент Яндекс.Музыки на npm - yandex-music-client&lt;/a&gt;
👉 Теперь VSCode-плагин для Яндекс.Музыки использует пакет &lt;a href=&quot;https://www.npmjs.com/package/yandex-music-client&quot;&gt;yandex-music-client&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Установк&lt;/strong&gt;а
&lt;code&gt;npm i yandex-music-clien&lt;/code&gt;t&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пример использовани&lt;/strong&gt;я&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;jsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { getToken } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;yandex-music-client/token&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { YandexMusicClient } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt; &apos;yandex-music-client/YandexMusicClient&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; token&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; getToken&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;your email&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&apos;your password&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; client&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; YandexMusicClient&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    BASE: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;https://api.music.yandex.net:443&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    HEADERS: {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;        &apos;Authorization&apos;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;`OAuth ${&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;token&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;client.landing.&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;getNewReleases&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;#javascript #yandexmusic #openapi&lt;/p&gt;</content:encoded></item><item><title>​​📖 Как браузер рендерит веб-страницу</title><link>https://cherkashin.dev/posts/74/</link><guid isPermaLink="true">https://cherkashin.dev/posts/74/</guid><description>​​📖 Как браузер рендерит веб-страницу

Для фронтенд-разработчиков очень важно знать, как происходит отрисовка веб-страницы на всех этапах: от отправки запроса на сервер до отображения картинки, которую мы видим в браузере.

Чтобы быстро разобраться в основах можно почитать следующие 3 статьи:

Дока - Как браузер рисуе...</description><pubDate>Fri, 23 Dec 2022 06:00:12 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/ba4b1b855e34f8a809bef.jpg&quot;&gt;​​&lt;/a&gt;📖 &lt;strong&gt;Как браузер рендерит веб-страницу&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Для фронтенд-разработчиков очень важно знать, как происходит отрисовка веб-страницы на всех этапах: от отправки запроса на сервер до отображения картинки, которую мы видим в браузере.&lt;/p&gt;
&lt;p&gt;Чтобы быстро разобраться в основах можно почитать следующие 3 статьи:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/js/how-the-browser-creates-pages/&quot;&gt;Дока - Как браузер рисует страницы&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rashidovr.medium.com/reflow-repaint-composite-%D1%87%D1%82%D0%BE-%D1%8D%D1%82%D0%BE-%D0%B8-%D0%BA%D0%B0%D0%BA-%D1%8D%D1%82%D0%BE-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D0%B5%D1%82-a777c5760295&quot;&gt;Reflow, Repaint, Composite — что это и как это работает?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/post/320430/&quot;&gt;Понимание критического пути рендеринга&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Затем, чтобы погрузиться в детали — можно прочитать статью:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/jspoint/how-the-browser-renders-a-web-page-dom-cssom-and-rendering-df10531c9969&quot;&gt;How the browser renders a web page? — DOM, CSSOM, and Rendering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А какие статьи помогли вам разобраться в теме?&lt;/p&gt;
&lt;p&gt;#fridayreading #javascript #browser #css #html #performance #rendering&lt;/p&gt;</content:encoded></item><item><title>​​☠️ Временная Мёртвая Зона</title><link>https://cherkashin.dev/posts/73/</link><guid isPermaLink="true">https://cherkashin.dev/posts/73/</guid><description>​​☠️ Временная Мёртвая Зона

Временная мёртвая зона (ВМЗ) — участок от начала блока кода, до строки, где переменная объявлена и инициализирована. Понятие ВМЗ применяется только к переменным определённым с помощью let и const.

Строки 2-5 — временная мёртвая зона. Область видимости переменной there началась (из-за “подн...</description><pubDate>Mon, 19 Dec 2022 07:00:12 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/723711be7c4e887c61647.jpg&quot;&gt;​​&lt;/a&gt;☠️ **Временная Мёртвая Зона&lt;/p&gt;
&lt;p&gt;**Временная мёртвая зона (ВМЗ) — участок от начала блока кода, до строки, где переменная объявлена и инициализирована. Понятие ВМЗ применяется только к переменным определённым с помощью &lt;code&gt;let&lt;/code&gt; и &lt;code&gt;const&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Строки 2-5 — временная мёртвая зона. Область видимости переменной &lt;code&gt;there&lt;/code&gt; началась (из-за “&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Hoisting&quot;&gt;поднятия&lt;/a&gt;” переменных в JS), но она всё еще не объявлена, поэтому при доступе к переменной произойдёт ошибка - &lt;code&gt;ReferenceError&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Строка 7 — конец временной мёртвой зоны&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Смысл временной мёртвой зоны — лёгкость нахождения ошибок доступа к неинициализированным переменным, с которыми мы встречаемся при использовании &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Подробнее можно &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz&quot;&gt;почитать на MDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#javascript&lt;/p&gt;</content:encoded></item><item><title>🚀 Деплой NodeJs приложений</title><link>https://cherkashin.dev/posts/72/</link><guid isPermaLink="true">https://cherkashin.dev/posts/72/</guid><description>🚀 Деплой NodeJs приложений

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

RenderRailwayVercel

Ещё по теме:

3 free Heroku alternatives to deploy a ...</description><pubDate>Mon, 12 Dec 2022 07:00:24 GMT</pubDate><content:encoded>&lt;p&gt;🚀 &lt;strong&gt;Деплой NodeJs приложений&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Недавно, ко всеобщему сожалению, heroku урезал свой бесплатный тариф для хостинга приложений, который использовался многими разработчиками для хостинга своих пэт проектов. В качестве альтернативы можно использовать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://render.com/&quot;&gt;Render&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://railway.app/&quot;&gt;Railway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vercel.com/&quot;&gt;Vercel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.logrocket.com/3-free-heroku-alternatives-deploy-node-js/&quot;&gt;3 free Heroku alternatives to deploy a Node.js app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vercel.com/guides/using-express-with-vercel&quot;&gt;Using Express.js with Vercel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;А каким бесплатным хостингом пользуетесь вы❓&lt;/p&gt;
&lt;p&gt;#deploy #nodejs&lt;/p&gt;</content:encoded></item><item><title>📖 Матрица компетенций</title><link>https://cherkashin.dev/posts/71/</link><guid isPermaLink="true">https://cherkashin.dev/posts/71/</guid><description>📖 Матрица компетенций

Сегодня порекомендую пару докладов о составлении матриц компетенций и о том, какие проблемы они решают:
1️⃣ Универсальная карта компетенций
2️⃣ Матрица компетенций как инструмент тимлида

Некоторые основные моменты из докладов.

❓Зачем нужна матрица скиллов?
Чтобы понимать

Компетенции текущих ч...</description><pubDate>Fri, 09 Dec 2022 09:02:22 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Матрица компетенций&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня порекомендую пару докладов о составлении матриц компетенций и о том, какие проблемы они решают:
1️⃣ &lt;a href=&quot;https://www.youtube.com/watch?v=aS2ymBX1VJw&amp;#x26;ab_channel=ManagementChannel&quot;&gt;Универсальная карта компетенций&lt;/a&gt;
2️⃣ &lt;a href=&quot;https://www.youtube.com/watch?v=ITCUNTovW3M&amp;#x26;t=2608s&amp;#x26;ab_channel=ManagementChannel&quot;&gt;Матрица компетенций как инструмент тимлида&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Некоторые основные моменты из докладов.&lt;/p&gt;
&lt;p&gt;❓&lt;strong&gt;Зачем нужна матрица скиллов?&lt;/strong&gt;
Чтобы понимать&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Компетенции текущих членов команды&lt;/li&gt;
&lt;li&gt;Каких компетенций не хватает команде, каких людей необходимо нанимать&lt;/li&gt;
&lt;li&gt;Ускорить онбординг новичков&lt;/li&gt;
&lt;li&gt;Оценить пробелы в знаниях, наметить план обучения, индивидуальные траектории роста&lt;/li&gt;
&lt;li&gt;Сделать понятным/прозрачным Performance Review&lt;/li&gt;
&lt;li&gt;Где может возникнуть Bus Factor. Вовремя понять где могут возникнуть проблемы при увольнении сотрудника.&lt;/li&gt;
&lt;li&gt;Насколько зарплата соответствует набору задач, которые решает разработчик&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🏁 &lt;strong&gt;Как начать?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Определить задачи, над которыми вы работаете, и какие знания необходимы для их выполнения: подходы, инструменты, навыки&lt;/li&gt;
&lt;li&gt;Определить текущие навыки каждого члена команды
&lt;ul&gt;
&lt;li&gt;Самооценка с последующей проверкой ведущим разработчиком/тимлидом&lt;/li&gt;
&lt;li&gt;Устроить опрос среди всех сотрудников и оценить каждого сотрудника&lt;/li&gt;
&lt;li&gt;Для каждого навыка определить чёткие критерии оценки&lt;/li&gt;
&lt;li&gt;Создать отдельную страницу/документ по каждому навыку со всеми известными материалами/ссылками, чтобы разработчик мог быстро изучить навык&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Один из способов оценки навыков:
&lt;ul&gt;
&lt;li&gt;0 - не знаю, не умею, не понимаю&lt;/li&gt;
&lt;li&gt;1 - немного знаю/могу делать простейшие задачи&lt;/li&gt;
&lt;li&gt;2 - достаточно много знаю/ могу делать большинство задач&lt;/li&gt;
&lt;li&gt;3 - знаю всё, могу сделать любую задачу, учу других&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🔄 &lt;strong&gt;Knowledge sharing&lt;/strong&gt;
Если разработчик чего-то не знает, это не его проблема, не его вина (ну почти). Это проблема компании и тимлида. Как заниматься распространением знаний в компании?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Написать документацию&lt;/li&gt;
&lt;li&gt;Провести внутренние обучающие сессии/доклады (knowledge sharing session)&lt;/li&gt;
&lt;li&gt;Купить обучающий курс для команды&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#teamlead #skills #knowledgesharing&lt;/p&gt;</content:encoded></item><item><title>VS Code Yandex Music Extension ❤️ MacOS и Linux</title><link>https://cherkashin.dev/posts/70/</link><guid isPermaLink="true">https://cherkashin.dev/posts/70/</guid><description>VS Code Yandex Music Extension ❤️ MacOS и Linux

Полтора года назад я выпустил первую более-менее стабильную версию расширения Яндекс.Музыки для VsCode. Разрабатывал я его в основном для себя, поэтому особо и не заморачивался, что поддерживается только винда, ведь именно виндой я пользовался. В прошлом феврале я перешё...</description><pubDate>Sun, 04 Dec 2022 15:44:01 GMT</pubDate><content:encoded>&lt;p&gt;**VS Code Yandex Music Extension **❤️ &lt;strong&gt;MacOS и Linux&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://t.me/cherkashindev/6&quot;&gt;Полтора года назад&lt;/a&gt; я выпустил первую более-менее стабильную версию расширения Яндекс.Музыки для VsCode. Разрабатывал я его в основном для себя, поэтому особо и не заморачивался, что поддерживается только винда, ведь именно виндой я пользовался. В прошлом феврале я перешёл на мак и с тех пор не пользовался расширением, как и все по старинке включал музыку в браузере. Пару недель назад решил всё-таки довести дело до конца и сделать расширение кроссплатформенным. Так вот, сегодня зарелизил новую версию, которая работает на всех операционках.&lt;/p&gt;
&lt;p&gt;🐞 &lt;strong&gt;Проблема&lt;/strong&gt;
Для воспроизведения музыки под капотом используется &lt;a href=&quot;https://www.electronjs.org/&quot;&gt;Electron&lt;/a&gt;. Проблема в том, что он собирается под каждую платформу отдельно, поэтому раньше поддерживалась лишь та операционная система, на которой происходила сборка расширения.&lt;/p&gt;
&lt;p&gt;✅ &lt;strong&gt;Решение&lt;/strong&gt;
Теперь Electron устанавливается в рантайме именно для вашей операционной системы при установке плагина YandexMusic с помощью пакета &lt;a href=&quot;https://github.com/electron/get&quot;&gt;@electron/get&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#vscode #yandexmusic #extension #macos #linux&lt;/p&gt;</content:encoded></item><item><title>📖 Пятничное чтиво - Turmoil in Twitter</title><link>https://cherkashin.dev/posts/69/</link><guid isPermaLink="true">https://cherkashin.dev/posts/69/</guid><description>📖 Пятничное чтиво - Turmoil in Twitter

С небольшим опозданием, если кто-то всё ещё не в курсе — Илон Маск купил твиттер, поэтому сегодня предлагаю прочитать именно об этом. Из неё вы во всех красках сможете узнать, как Маск собирается сделать Twitter прибыльной компанией в рекордные сроки.

Несколько моментов из стат...</description><pubDate>Fri, 25 Nov 2022 06:29:20 GMT</pubDate><content:encoded>&lt;p&gt;📖 **Пятничное чтиво - &lt;strong&gt;&lt;a href=&quot;https://newsletter.pragmaticengineer.com/p/the-scoop-turmoil-at-twitter&quot;&gt;&lt;strong&gt;Turmoil in Twitter&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt;
**
С небольшим опозданием, если кто-то всё ещё не в курсе — Илон Маск купил твиттер, поэтому сегодня предлагаю прочитать именно об этом. Из неё вы во всех красках сможете узнать, как Маск собирается сделать Twitter прибыльной компанией в рекордные сроки.&lt;/p&gt;
&lt;p&gt;Несколько моментов из статьи:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Разработчиков Твиттера попросили распечатать их код для ревью с Маском и инженерами из Теслы, а затем без ревью попросили уничтожить все распечатки в шредере&lt;/li&gt;
&lt;li&gt;В субботу утром был анонсирован новый проект — те самые верификационные галочки, а демо назначено на понедельник. То есть, Маск косвенно заставил многих работать на выходных&lt;/li&gt;
&lt;li&gt;Даже некоторые из тех, кто работал по выходным над новой фичей, вскоре были уволены&lt;/li&gt;
&lt;li&gt;Маск никак не общался с работниками Твиттера через официальные каналы, разработчики обо всем узнавали из новостей&lt;/li&gt;
&lt;li&gt;Маск может быть самым богатым человеком в мире в настоящее время, но он определенно не идеальный босс для людей, которые ценят выходные для себя и своей семьи&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;||Статье уже 3 недели. Если вы знаете продолжение истории было бы круто, если бы вы рассказали в комментариях. Ссылки на источники приветствуются 👍.||&lt;/p&gt;
&lt;p&gt;#fridayreading&lt;/p&gt;</content:encoded></item><item><title>​​💳 Карта UnionPay в 2022</title><link>https://cherkashin.dev/posts/68/</link><guid isPermaLink="true">https://cherkashin.dev/posts/68/</guid><description>​​💳 Карта UnionPay в 2022

Последний отпуск я ездил в Турцию, поэтому, чтобы чувствовать себя белым человеком и платить картой, решил выпустить карту Union Pay Русского Стандарта.

Основные моменты:

Карта не именная, поэтому можно сделать за один деньОбслуживание 3000 в годДвойная конвертация - Лиры ⇒ Юани ⇒ Рубли. П...</description><pubDate>Tue, 22 Nov 2022 06:00:23 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/7689c967f537ae3aba28f.jpg&quot;&gt;​​&lt;/a&gt;💳 &lt;strong&gt;Карта UnionPay в 2022&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Последний отпуск я ездил в Турцию, поэтому, чтобы чувствовать себя белым человеком и платить картой, решил выпустить &lt;a href=&quot;https://www.rsb.ru/cards/union-pay/&quot;&gt;карту Union Pay Русского Стандарта&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Основные моменты:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Карта не именная, поэтому можно сделать за один день&lt;/li&gt;
&lt;li&gt;Обслуживание 3000 в год&lt;/li&gt;
&lt;li&gt;Двойная конвертация - Лиры ⇒ Юани ⇒ Рубли. Поэтому курс может быть немного хуже официального. Но гораздо выгоднее чем покупать доллары и рубли в Российских банках. Например, если курс лиры - 3.2, то у вам посчитается примерно по курсу 3.4-3.5 рубля за лиру&lt;/li&gt;
&lt;li&gt;Комиссия за снятие в банкоматах - 2%, минимум 100 рублей&lt;/li&gt;
&lt;li&gt;Если вы пытаетесь использовать карту за границей и она не работает, проверьте, возможно данный банк не поддерживает карты UnionPay. Так в Черногории нет ни одного банка, который бы работал с данной платёжной системой, а в Азербайджане с UnionPay работает всего один банк.&lt;/li&gt;
&lt;li&gt;При снятии наличных в банкомате может отображаться неверная сумма, списанная в рублях. После того как операция будет подтверждена, в приложении отобразится корректная сумма. Это наглядно можно увидеть на картинке.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Турция:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Карта работает буквально везде&lt;/li&gt;
&lt;li&gt;Не всегда проходит оплата в долларах, оплата в лирах работает стабильно&lt;/li&gt;
&lt;li&gt;Не всегда работает бесконтактная оплата, чип работает стабильно&lt;/li&gt;
&lt;li&gt;В банкоматах можно снимать как лиры, так доллары и евро&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Сербия:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Всё почти также хорошо, как и в Турции. Большинство банков работает с UnionPay. Но не все, я не смог снять наличку в местном Райффайзен банке.&lt;/li&gt;
&lt;li&gt;В магазинах обычно установлено два терминала. Если оплата на первом не проходит — уточняют “UnionPay?” и просят оплатить на втором терминале. Кассир в Заре сказала, что сейчас многие русские используют UnionPay.&lt;/li&gt;
&lt;li&gt;Лучше иметь с собой наличные, в некоторых магазинах и кафе не получится оплатить через UnionPay.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ещё о UnionPay:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://relocation.guide/&quot;&gt;Гайд в свободный мир - UnionPay&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/spreadsheets/d/1sBbGej3ZTSnfhmfh_v4brTZCo_f7BxEE4p8HInrh2zc/edit#gid=61373499&quot;&gt;Опросник по работе карт UnionPay выпущенных банками РФ (СНГ)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>📖Пятничное чтиво - Compound Components</title><link>https://cherkashin.dev/posts/67/</link><guid isPermaLink="true">https://cherkashin.dev/posts/67/</guid><description>📖Пятничное чтиво - Compound Components

Сегодня советы для React разработчиков. Если вы не знаете, что делать со сложными компонентами, пишите сложные рендеры и используете кучу вложенных тернарников, то рекомендую ознакомиться с подходом Compound Components:

👉 Александр Дунай (Альфа-Банк) — Улучшаем качество кода R...</description><pubDate>Fri, 18 Nov 2022 07:00:08 GMT</pubDate><content:encoded>&lt;p&gt;📖&lt;strong&gt;Пятничное чтиво - Compound Components&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня советы для React разработчиков. Если вы не знаете, что делать со сложными компонентами, пишите сложные рендеры и используете кучу вложенных тернарников, то рекомендую ознакомиться с подходом Compound Components:&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://www.youtube.com/watch?v=4BByJUk5x7M&quot;&gt;Александр Дунай (Альфа-Банк) — Улучшаем качество кода React-приложения с помощью Compound Components&lt;/a&gt;
👉 &lt;a href=&quot;https://kentcdodds.com/blog/compound-components-with-react-hooks&quot;&gt;Kent C. Dodds - React Hooks: Compound Components&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #react&lt;/p&gt;</content:encoded></item><item><title>📖Пятничное чтиво</title><link>https://cherkashin.dev/posts/66/</link><guid isPermaLink="true">https://cherkashin.dev/posts/66/</guid><description>📖Пятничное чтиво

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

Управление проектами – управление людьмиКак поймать «поток», и как сделать так, чтобы он не сорвался

#fridayreading #timemanagement</description><pubDate>Fri, 11 Nov 2022 06:02:53 GMT</pubDate><content:encoded>&lt;p&gt;📖&lt;strong&gt;Пятничное чтиво&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня без лишних слов хотел бы порекомендовать пару коротких статей, которые пригодятся всем начинающим руководителям (да и их подопечным).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/post/83837/&quot;&gt;Управление проектами – управление людьми&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/post/103572/&quot;&gt;Как поймать «поток», и как сделать так, чтобы он не сорвался&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #timemanagement&lt;/p&gt;</content:encoded></item><item><title>Система личного планирования в Notion. Эпизод 2 — Управление проектами</title><link>https://cherkashin.dev/posts/65/</link><guid isPermaLink="true">https://cherkashin.dev/posts/65/</guid><description>Система личного планирования в Notion. Эпизод 2 — Управление проектами

В начале недели вышла первая часть статьи, где я рассказал о Инбоксе и о различных способах его настройки.

Пришло время рассмотреть вторую часть, где мы поговорим:

О том как вести проекты и задачиЧто такое еженедельный обзорЧто такое такое област...</description><pubDate>Sat, 05 Nov 2022 07:29:55 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/696698/&quot;&gt;Система личного планирования в Notion. Эпизод 2 — Управление проектами&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;В начале недели вышла &lt;a href=&quot;https://habr.com/ru/post/696416/&quot;&gt;первая часть статьи&lt;/a&gt;, где я рассказал о Инбоксе и о различных способах его настройки.&lt;/p&gt;
&lt;p&gt;Пришло время рассмотреть вторую часть, где мы поговорим:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;О том как вести проекты и задачи&lt;/li&gt;
&lt;li&gt;Что такое еженедельный обзор&lt;/li&gt;
&lt;li&gt;Что такое такое области ответственности&lt;/li&gt;
&lt;li&gt;Как настроить автоматические бэкапы&lt;/li&gt;
&lt;li&gt;Как скопировать мой шаблон и сразу начать его использовать&lt;/li&gt;
&lt;li&gt;Как модифицировать систему под ваши нужды&lt;/li&gt;
&lt;li&gt;Для чего лучше не использовать систему планирования&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем, читаем, ставим лайки, подписываемся на канал 😃.&lt;/p&gt;
&lt;p&gt;#notion #gtd #planning #PARA&lt;/p&gt;</content:encoded></item><item><title>Система личного планирования в Notion. Эпизод 2 — Управление проектами</title><link>https://cherkashin.dev/articles/personal-planning-system-in-notion-2/</link><guid isPermaLink="true">https://cherkashin.dev/articles/personal-planning-system-in-notion-2/</guid><description>Вот уже чуть больше года я активно использую Notion для планирования задач и проектов, поэтому я решил подвести некоторые итоги и систематизировать все приёмы, которые я использую. Как вы уже поняли из названия - это вторая часть, описываемой системы. В первой части я подробно рассмотрел работу с инбоксом, вторая часть будет посвящена непосредственно &quot;Управлению проектами&quot;. Обе части полностью независимы и могут читаться по отдельности, но я всё равно рекомендую с ней ознакомиться (ссылка на первую часть о инбоксе) и настроить один их способов наполнения инбокса.</description><pubDate>Sat, 05 Nov 2022 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/personal-planning-system-in-notion-2/image1.jpg" medium="image"/><media:thumbnail url="https://cherkashin.dev/personal-planning-system-in-notion-2/image1.jpg"/></item><item><title>Система личного планирования в Notion. Эпизод 1 — Инбокс</title><link>https://cherkashin.dev/posts/64/</link><guid isPermaLink="true">https://cherkashin.dev/posts/64/</guid><description>Система личного планирования в Notion. Эпизод 1 — Инбокс

Наконец-то, спустя пару тройку месяцев, я смог заставить себя сесть и дописать статью о том, как я пользуюсь Notion. Пока опубликовал лишь только первую часть, на следующей неделе должен закончить и вторую.

Было бы круто, если бы вы поделились, какими программа...</description><pubDate>Tue, 01 Nov 2022 06:34:54 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/696416/&quot;&gt;Система личного планирования в Notion. Эпизод 1 — Инбокс&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Наконец-то, спустя пару тройку месяцев, я смог заставить себя сесть и дописать статью о том, как я пользуюсь Notion. Пока опубликовал лишь только первую часть, на следующей неделе должен закончить и вторую.&lt;/p&gt;
&lt;p&gt;Было бы круто, если бы вы поделились, какими программами и методологиями вы пользуетесь для ведения Инбокса и Системы планирования в целом.&lt;/p&gt;
&lt;p&gt;#notion #gtd #planning&lt;/p&gt;</content:encoded></item><item><title>Система личного планирования в Notion. Эпизод 1 — Инбокс</title><link>https://cherkashin.dev/articles/personal-planning-system-in-notion-1/</link><guid isPermaLink="true">https://cherkashin.dev/articles/personal-planning-system-in-notion-1/</guid><description>Вот уже чуть больше года я активно использую Notion для планирования задач и проектов, поэтому я решил подвести некоторые итоги и систематизировать все приёмы, которые я использую. Описание системы будет состоять из двух частей. В первой части, я хотел бы уделить отдельное внимание Инбоксу — одной из самых важных составляющих удобной системы планирования. Вторая часть будет посвящена непосредственно Управлению проектами.</description><pubDate>Tue, 01 Nov 2022 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/personal-planning-system-in-notion-1/support-notion-1.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/personal-planning-system-in-notion-1/support-notion-1.png"/></item><item><title>📖Пятничное чтиво - Преемник</title><link>https://cherkashin.dev/posts/63/</link><guid isPermaLink="true">https://cherkashin.dev/posts/63/</guid><description>📖Пятничное чтиво - Преемник

Наконец-то в отпуске смог дочитать книгу “Преемник”, которую заказал ещё в начале года.

Удивительно, как жизнь одного человека может описать судьбу страны последних 30 лет. Книга проводит нас по всем основным событиям, которые случились после распада СССР, и описывает события, которые про...</description><pubDate>Fri, 28 Oct 2022 07:33:11 GMT</pubDate><content:encoded>&lt;p&gt;📖&lt;strong&gt;Пятничное чтиво - Преемник&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Наконец-то в отпуске смог дочитать книгу “Преемник”, которую заказал ещё в начале года.&lt;/p&gt;
&lt;p&gt;Удивительно, как жизнь одного человека может описать судьбу страны последних 30 лет. Книга проводит нас по всем основным событиям, которые случились после распада СССР, и описывает события, которые произошли уже в современной России:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Путч&lt;/li&gt;
&lt;li&gt;Чеченские войны&lt;/li&gt;
&lt;li&gt;Дефолт&lt;/li&gt;
&lt;li&gt;Норд Ост&lt;/li&gt;
&lt;li&gt;События на Болотной площади&lt;/li&gt;
&lt;li&gt;и так далее&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Прочитав книгу, можно знать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;На какие сделки и компромиссы нужно идти в политической борьбе&lt;/li&gt;
&lt;li&gt;Почему решения в нашей стране принимаются именно так, как они сейчас принимаются&lt;/li&gt;
&lt;li&gt;Как случилось так, что вся опозиция либо “сидит” либо находится за границей&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Все события описываются так, что ощущение что ты сам находишься в эпицентре событий.&lt;/p&gt;
&lt;p&gt;#fridayreading #politics #book&lt;/p&gt;</content:encoded></item><item><title>📖Пятничное чтиво</title><link>https://cherkashin.dev/posts/61/</link><guid isPermaLink="true">https://cherkashin.dev/posts/61/</guid><description>📖Пятничное чтиво

Я купил книгу Getting Things Done (GTD) около 3 лет назад и только в этом году у меня дошли руки, чтобы прочесть её. Вчера наткнулся на статью GTD за 15 минут: прагматическое руководство. Неплохо подходит, не только чтобы освежить всё это в памяти, но и как краткий экскурс в GTD. Поэтому рекомендую к...</description><pubDate>Fri, 07 Oct 2022 07:00:05 GMT</pubDate><content:encoded>&lt;p&gt;📖**Пятничное чтиво
**
Я купил книгу Getting Things Done (GTD) около 3 лет назад и только в этом году у меня дошли руки, чтобы прочесть её. Вчера наткнулся на статью &lt;a href=&quot;https://habr.com/ru/company/wunderfund/blog/648663/&quot;&gt;GTD за 15 минут: прагматическое руководство&lt;/a&gt;. Неплохо подходит, не только чтобы освежить всё это в памяти, но и как краткий экскурс в GTD. Поэтому рекомендую к прочтению.&lt;/p&gt;
&lt;p&gt;Основные моменты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GTD - это методика организации и отслеживания задач и проектов&lt;/li&gt;
&lt;li&gt;Цель GTD — сделать так, чтобы человек полностью доверял бы системе сбора задач, идей и проектов&lt;/li&gt;
&lt;li&gt;Техника GTD основана на ведении списков:
&lt;ul&gt;
&lt;li&gt;Входящие (Инбокс)&lt;/li&gt;
&lt;li&gt;Следующие действия&lt;/li&gt;
&lt;li&gt;Список ожидания&lt;/li&gt;
&lt;li&gt;Проекты&lt;/li&gt;
&lt;li&gt;Когда-нибудь/может быть&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Основная цель инбокса — разгрузить мозг. Просто записывайте все мысли, задачи, проекты, которые приходят вам в голову в инбокс.&lt;/li&gt;
&lt;li&gt;Инбокс необходимо обрабатывать регулярно.&lt;/li&gt;
&lt;li&gt;Определение следующего действия, которое должно быть физическим, видимым действием, приближающим проект к его цели — самое важное «правило» GTD.&lt;/li&gt;
&lt;li&gt;Если вы делегировали задачу другому человеку, если вы отправили email  и ждёте ответа — внесите это в “Список Ожидания”&lt;/li&gt;
&lt;li&gt;Проект — это любая цель, для достижения которой нужно выполнить более одного действия&lt;/li&gt;
&lt;li&gt;Контексты действий — это «теги», которыми снабжают элементы в списках Следующие действия. Они представляют собой сведения о том, где может быть выполнено то или иное действие, или о том, что именно нужно для его выполнения.&lt;/li&gt;
&lt;li&gt;Еженедельный обзор — актуализация списков следующих действий и проектов. Что-то нужно перенести из списка Когда-нибудь/Может быть в список следующих действий, что-то необходимо удалить совсем, потому что это больше не актуально.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #gtd #planning&lt;/p&gt;</content:encoded></item><item><title>​​Диаграммы  - Mermaid</title><link>https://cherkashin.dev/posts/60/</link><guid isPermaLink="true">https://cherkashin.dev/posts/60/</guid><description>​​Диаграммы  - Mermaid

Хорошо нарисованная диаграмма может объяснить концепцию гораздо лучше текста, к тому же диаграмму гораздо легче понять, ведь вам не нужно ничего визуализировать у себя в голове пока вы читаете текст.
Особенно часто приходится рисовать диаграммы при написании документации к коду, например, когда ...</description><pubDate>Tue, 27 Sep 2022 07:00:09 GMT</pubDate><content:encoded>&lt;p&gt;​​&lt;a href=&quot;https://telegra.ph/file/fc620db4125841c79ebc5.jpg&quot;&gt;&lt;strong&gt;Диаграммы&lt;/strong&gt;&lt;/a&gt;**  - Mermaid**&lt;/p&gt;
&lt;p&gt;Хорошо нарисованная диаграмма может объяснить концепцию гораздо лучше текста, к тому же диаграмму гораздо легче понять, ведь вам не нужно ничего визуализировать у себя в голове пока вы читаете текст.
Особенно часто приходится рисовать диаграммы при написании документации к коду, например, когда необходимо нарисовать архитектуру проекта или его части.
Для создания диаграмм очень удобно использовать &lt;a href=&quot;https://mermaid-js.github.io/mermaid/#/&quot;&gt;Mermaid&lt;/a&gt;. Синтаксис выглядит следующим образом:&lt;/p&gt;
&lt;p&gt;&lt;code&gt; graph TD;   A--&gt;B;   A--&gt;C;   B--&gt;D;   C--&gt;D;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;К тому же Mermaid поддерживается:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/&quot;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.gitlab.com/ee/user/markdown.html#mermaid&quot;&gt;GitLab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lukemerrett.com/using-mermaid-flowchart-syntax-in-notion/&quot;&gt;Notion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Таким образом, вы можете хранить ваши диаграммы прямо в Markdown разметке. Просто нарисуйте вашу диаграмму в &lt;a href=&quot;https://mermaid-js.github.io/mermaid-live-editor/&quot;&gt;Mermaid Live Editor&lt;/a&gt; и скопируйте код в вашу документацию. Больше не нужно хранить диаграммы в виде картинок и искать исходники каждый раз, когда необходимо внести правки! Все ваши диаграммы — просто код.&lt;/p&gt;
&lt;p&gt;#notion #documentation #github #gitlab&lt;/p&gt;</content:encoded></item><item><title>Реализация Completed Date для задач в Notion</title><link>https://cherkashin.dev/posts/58/</link><guid isPermaLink="true">https://cherkashin.dev/posts/58/</guid><description>Реализация Completed Date для задач в Notion

Последний год я использую Notion для ведения задач и проектов. Иногда полезно оглянуться и посмотреть, чем я занимался последний месяц или в четверг прошлой недели.

Первое, что приходит в голову добавить поле Completed At и выставлять его вручную при завершении задачи, но ...</description><pubDate>Sun, 18 Sep 2022 08:18:06 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Реализация Completed Date для задач в Notion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Последний год я использую Notion для ведения задач и проектов. Иногда полезно оглянуться и посмотреть, чем я занимался последний месяц или в четверг прошлой недели.&lt;/p&gt;
&lt;p&gt;Первое, что приходит в голову добавить поле &lt;code&gt;Completed At&lt;/code&gt; и выставлять его вручную при завершении задачи, но удобства в этом мало. Никаких готовых решений, типа вэбхука, который будет вызываться при завершении задачи и выставлять текущую дату я не нашёл.&lt;/p&gt;
&lt;p&gt;К счастью у Notion есть публичный API, который можно использовать для этих целей. Алгоритм следующий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Получить все задачи изменённые сегодня и с пустым полем &lt;code&gt;Completed At&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Среди полученных задач выбрать те, что в списке &lt;code&gt;Done&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Выставить значение &lt;code&gt;Modified At&lt;/code&gt; в поле &lt;code&gt;Completed At&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Скрипт, реализующий этот алгоритм, запускается каждый час с помощью GitHub Actions. Теперь вы можете просто добавить новое представление Done для вашей таблицы задач.&lt;/p&gt;
&lt;p&gt;Исходники скрипта, можно найти &lt;a href=&quot;https://github.com/acherkashin/completed-date-notion&quot;&gt;здесь в репозитории на GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#notion&lt;/p&gt;</content:encoded></item><item><title>🧼 Экранирование и санитайзинг</title><link>https://cherkashin.dev/posts/57/</link><guid isPermaLink="true">https://cherkashin.dev/posts/57/</guid><description>🧼 Экранирование и санитайзинг

Для предотвращения XSS существует 2 техники:

Экранирование (Escaping) - замена опасных символов, их безопасными аналогами. Например “&gt;” будет заменён на &quot;&gt;&quot;, “&lt;” — &quot;&lt;&quot;. Это необходимо, так как символы “&lt;”, “&gt;” в HTML имеют особое значение - они определяют начало и конец html-тэга.

Сани...</description><pubDate>Mon, 12 Sep 2022 07:00:10 GMT</pubDate><content:encoded>&lt;p&gt;🧼 &lt;strong&gt;Экранирование и санитайзинг&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Для предотвращения XSS существует 2 техники:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Экранирование (Escaping)&lt;/strong&gt; - замена опасных символов, их безопасными аналогами. Например “&gt;” будет заменён на ”&gt;”, “&amp;#x3C;” — ”&amp;#x3C;“. Это необходимо, так как символы “&amp;#x3C;”, “&gt;” в HTML имеют особое значение - они определяют начало и конец html-тэга.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Санитайзинг (Sanitization)&lt;/strong&gt; - удаление вредоносного текста в строке. Например, удаление тэга script - “Hello &lt;script&gt;world()&lt;/script&gt;” ⇒ “Hello”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;В каком случае использовать какую технику?&lt;/strong&gt;
Всегда используйте экранирование, санитайзинг должен быть использован лишь тогда, когда вы хотите позволить пользователю вводить отформатированный текст. Иными словами используйте санитайзинг, только для отображения строки, полученной с помощью &lt;a href=&quot;https://ru.wikipedia.org/wiki/WYSIWYG&quot;&gt;WYSIWYG&lt;/a&gt; редактора.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Почему?&lt;/strong&gt;
Цель санитайзинга - удалить лишь опасный текст — это javascript-код, который может быть выполнен в браузере пользователя. При этом тэги &lt;code&gt;&amp;#x3C;b&gt;&lt;/code&gt;, &lt;code&gt;&amp;#x3C;img&gt;&lt;/code&gt;, &lt;code&gt;&amp;#x3C;p&gt;&lt;/code&gt; не несут в себе никакой опасности и они не всегда должны быть удалены из строки. &lt;strong&gt;Но, если мы будем использовать санитайзинг вместо экранирования, данные тэги могут сломать разметку нашего приложения.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/post/182424/&quot;&gt;Экранирование (или что нужно знать для работы с текстом в тексте)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part2.html&quot;&gt;Preventing XSS in React (Part 2): dangerouslySetInnerHTML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#xss #security #frontend&lt;/p&gt;</content:encoded></item><item><title>📖 Пятничное чтиво</title><link>https://cherkashin.dev/posts/56/</link><guid isPermaLink="true">https://cherkashin.dev/posts/56/</guid><description>📖 Пятничное чтиво

Пятничное чтиво с небольшим опазданием. Время от времени пишу о том, как я использую Notion. Сегодня решил порекомендовать статью о появлении любимого сервиса.

История успеха Notion: из конструктора сайтов в универсальную базу знаний

#fridayreading #notion</description><pubDate>Sat, 10 Sep 2022 10:51:52 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Пятничное чтиво&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Пятничное чтиво с небольшим опазданием. Время от времени пишу о том, как я использую Notion. Сегодня решил порекомендовать статью о появлении любимого сервиса.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://vc.ru/u/93158-dmitriy-begovatov/477680-istoriya-uspeha-notion-iz-konstruktora-saytov-v-universalnuyu-bazu-znaniy&quot;&gt;История успеха Notion: из конструктора сайтов в универсальную базу знаний&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#fridayreading #notion&lt;/p&gt;</content:encoded></item><item><title>XSS в React</title><link>https://cherkashin.dev/posts/55/</link><guid isPermaLink="true">https://cherkashin.dev/posts/55/</guid><description>XSS в React

Одним из самых больших преимуществ реакта является его безопасный дизайн, который предотвращает появление большинства XSS (Cross-Site-Scripting) уязвимостей.

Может показаться что, если вы используете реакт, то вы в безопасности, ведь:
● React по-умолчанию экранирует текст, перед тем как его отрендерить
● ...</description><pubDate>Wed, 07 Sep 2022 06:58:19 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;XSS в React&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Одним из самых больших преимуществ реакта является его безопасный дизайн, который предотвращает появление большинства XSS (Cross-Site-Scripting) уязвимостей.&lt;/p&gt;
&lt;p&gt;Может показаться что, если вы используете реакт, то вы в безопасности, ведь:
● React по-умолчанию экранирует текст, перед тем как его отрендерить
● &lt;a href=&quot;https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml&quot;&gt;dangerouslySetInnerHTML&lt;/a&gt; не позволяет рендерить тэг &lt;code&gt;script&lt;/code&gt; и просто удаляет его&lt;/p&gt;
&lt;p&gt;Однако это не так. В реакт всё ещё существуют способы эксплуатации XSS уязвимостей.&lt;/p&gt;
&lt;p&gt;1️⃣ &lt;strong&gt;JavaScript URL - href аттрибут&lt;/strong&gt;
В реакте всё ещё возможно использовать &lt;code&gt;javascript:&lt;/code&gt; схему вместо &lt;code&gt;http:&lt;/code&gt; и &lt;code&gt;https:&lt;/code&gt; для эксплуатации XSS. Например, если приложение позволяет вводить URL, то пользователь может ввести следующий адрес &lt;code&gt;javascript:alert(&apos;&lt;/code&gt;XSS&lt;code&gt;&apos;)&lt;/code&gt; . В таком случае указанный javascript код будет выполнен, когда пользователь попытается перейти по ссылке. Поэтому очень важно валидировать полученный url.&lt;/p&gt;
&lt;p&gt;2️⃣ &lt;strong&gt;dangerouslySetInnerHTML&lt;/strong&gt;
В данном случае имя свойства говорит само за себя. Несмотря на то, что оно не позволяет рендерить тэг &lt;code&gt;script&lt;/code&gt;, есть множество иных способов эксплуатации XSS с помощью этого поля. Один из самых простых примеров - использование тэга &lt;code&gt;img&lt;/code&gt; вместе с &lt;code&gt;onerror&lt;/code&gt;. Больше примеров можно найти &lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html&quot;&gt;здесь&lt;/a&gt;. Поэтому свойство dangerouslySetInnerHTML должно использоваться в связке с библиотекой &lt;a href=&quot;https://github.com/cure53/DOMPurify&quot;&gt;DOMPurify&lt;/a&gt; для предотвращения XSS.&lt;/p&gt;
&lt;p&gt;3️⃣ &lt;strong&gt;Native API&lt;/strong&gt;
Если по каким-то причинам, вам необходимо использовать нативный API браузера, то в данном случае важно быть в двойне осторожным, ведь тут реакт уже не поможет:
● Постарайтесь использовать &lt;code&gt;innerText&lt;/code&gt; вместо &lt;code&gt;innerHTML&lt;/code&gt;
●  Вы все также можете использовать библиотеку &lt;a href=&quot;https://github.com/cure53/DOMPurify&quot;&gt;DOMPurify&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Чтобы подробнее ознакомиться с предотвращением XSS уязвимостей в React приложении советую прочитать следующий цикл статей:
● &lt;a href=&quot;https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part1.html&quot;&gt;Preventing XSS in React (Part 1): Data binding and URLs&lt;/a&gt;
● &lt;a href=&quot;https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part2.html&quot;&gt;Preventing XSS in React (Part 2): dangerouslySetInnerHTML&lt;/a&gt;
● &lt;a href=&quot;https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part3.html&quot;&gt;Preventing XSS in React (Part 3): escape hatches and component parsers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#xss #react #security #frontend&lt;/p&gt;</content:encoded></item><item><title>Новое свойство Статус в Notion</title><link>https://cherkashin.dev/posts/53/</link><guid isPermaLink="true">https://cherkashin.dev/posts/53/</guid><description>Новое свойство Статус в Notion

По многочисленным просьбам Notion добавил новое свойство Status. У него много преимуществ, почитать о них можно вот здесь, в официальной документации Notion, если больше нравится видео формат - то посмотреть можно здесь.

Для своей системы планирования я выделяю 2 главных преимущества:

...</description><pubDate>Thu, 30 Jun 2022 08:07:22 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Новое свойство Статус в Notion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;По многочисленным просьбам Notion добавил новое свойство &lt;code&gt;Status&lt;/code&gt;. У него много преимуществ, почитать о них можно &lt;a href=&quot;https://www.notion.so/help/guides/status-property-gives-clarity-on-tasks&quot;&gt;вот здесь, в официальной документации Notion&lt;/a&gt;, если больше нравится видео формат - &lt;a href=&quot;https://www.youtube.com/watch?v=XTrhCE0UfG4&quot;&gt;то посмотреть можно здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Для своей системы планирования я выделяю 2 главных преимущества:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;У статуса, есть значение по-умолчанию. Больше не будет задач, у которых пустой статус 🎉&lt;/li&gt;
&lt;li&gt;Можно легко мигрировать с поля &lt;code&gt;Select&lt;/code&gt;, которое часто использовалось в качестве поля &lt;code&gt;Status&lt;/code&gt;. Достаточно просто изменить тип поля на &lt;code&gt;Status&lt;/code&gt; и он автоматически конвертирует все значения. Ни фильтры, ни доски, после конвертации не пострадают.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Пример конвертации селекта в статус в комментариях.&lt;/p&gt;
&lt;p&gt;#notion&lt;/p&gt;</content:encoded></item><item><title>​​Интеграция Notion и Алисы 💥</title><link>https://cherkashin.dev/posts/51/</link><guid isPermaLink="true">https://cherkashin.dev/posts/51/</guid><description>​​Интеграция Notion и Алисы 💥

В одном из предыдущих постов я писал, как настроить интеграцию между Notion и Apple Shortcuts. Сегодня (дабы поддержать отечественного производителя) расскажу об интеграции Notion и Алисы.

Настраивается всё очень просто — инструкцию можете найти здесь. Если кратко, то процесс интеграции...</description><pubDate>Sun, 19 Jun 2022 12:57:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/27958a6689b81d7c3390e.mp4&quot;&gt;​​&lt;/a&gt;&lt;strong&gt;Интеграция Notion и Алисы&lt;/strong&gt; 💥&lt;/p&gt;
&lt;p&gt;В одном из &lt;a href=&quot;https://t.me/cherkashindev/43&quot;&gt;предыдущих постов&lt;/a&gt; я писал, как настроить интеграцию между Notion и Apple Shortcuts. Сегодня (дабы поддержать отечественного производителя) расскажу об интеграции Notion и Алисы.&lt;/p&gt;
&lt;p&gt;Настраивается всё очень просто — инструкцию можете найти &lt;a href=&quot;https://www.notion.so/e8da9e9e4b2545aaa163f56de7995973&quot;&gt;здесь&lt;/a&gt;. Если кратко, то процесс интеграции выглядит следующим образом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Создаёте новую интеграцию &lt;a href=&quot;https://www.notion.so/my-integrations&quot;&gt;тут&lt;/a&gt; и копируете токен&lt;/li&gt;
&lt;li&gt;Копируете идентификатор страницы или базы данных&lt;/li&gt;
&lt;li&gt;Отправляете всё в &lt;a href=&quot;https://dialogs.yandex.ru/store/skills/2d8532fa-dobavit-v-noush&quot;&gt;навык&lt;/a&gt; и всё готово&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Навык отлично подходит для добавления дел в инбокс. Если вы (как и я) ведёте список дел в базе данных, то при конфигурации укажите её идентификатор, тогда навык будет добавлять новые строки. Если вы укажите идентификатор страницы, то навык будет добавлять новую запись в to-do list.&lt;/p&gt;
&lt;p&gt;Если вы хотите поучаствовать в разработке навыка, то вот &lt;a href=&quot;https://github.com/kodilo-inc/notion-alice&quot;&gt;здесь найдёте исходники навыка&lt;/a&gt;. Если у вас есть какие-то предложения по улучшению навыка вступайте вот в &lt;a href=&quot;https://t.me/aliceAddToNotion&quot;&gt;этот чат&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#planning #notion #timemanagement #алиса&lt;/p&gt;</content:encoded></item><item><title>🎥 Пятничное чтиво</title><link>https://cherkashin.dev/posts/48/</link><guid isPermaLink="true">https://cherkashin.dev/posts/48/</guid><description>🎥 Пятничное чтиво

Сегодня не чтиво, а скорее смотриво. Приближаются выходные, самое время для сериалов, но коротких, чтобы успеть досмотреть и не отвлекаться в течении рабочей недели.

Пару месяцев назад посмотрел сериал Выбывшая. Рекомендую посмотреть, чтобы понять, как начинаются стартапы, и на что приходится идти ...</description><pubDate>Fri, 10 Jun 2022 06:57:03 GMT</pubDate><content:encoded>&lt;p&gt;**🎥 Пятничное чтиво&lt;/p&gt;
&lt;p&gt;**Сегодня не чтиво, а скорее **смотриво. **Приближаются выходные, самое время для сериалов, но коротких, чтобы успеть досмотреть и не отвлекаться в течении рабочей недели.&lt;/p&gt;
&lt;p&gt;Пару месяцев назад посмотрел сериал &lt;a href=&quot;https://www.kinopoisk.ru/series/1263786/&quot;&gt;Выбывшая&lt;/a&gt;. Рекомендую посмотреть, чтобы понять, как начинаются стартапы, и на что приходится идти чтобы они не потонули. Правда в этом случае, основатели зашли слишком далеко. Фильм основан на реальных событиях.&lt;/p&gt;
&lt;p&gt;#fridayreading&lt;/p&gt;</content:encoded></item><item><title>WAI-ARIA Authoring Practices перенесли сюда и обновили дизайн - не теряйте!</title><link>https://cherkashin.dev/posts/47/</link><guid isPermaLink="true">https://cherkashin.dev/posts/47/</guid><description>WAI-ARIA Authoring Practices перенесли сюда и обновили дизайн - не теряйте!

#frontend #accessibility</description><pubDate>Wed, 08 Jun 2022 09:26:47 GMT</pubDate><content:encoded>&lt;p&gt;WAI-ARIA Authoring Practices перенесли &lt;a href=&quot;https://www.w3.org/WAI/ARIA/apg/patterns/&quot;&gt;сюда&lt;/a&gt; и обновили дизайн - не теряйте!&lt;/p&gt;
&lt;p&gt;#frontend #accessibility&lt;/p&gt;</content:encoded></item><item><title>📖 Пятничное чтиво</title><link>https://cherkashin.dev/posts/46/</link><guid isPermaLink="true">https://cherkashin.dev/posts/46/</guid><description>📖 Пятничное чтиво

Как жалобы перенастраивают ваш мозг на негатив

Статья описывает, как мы меняемся при постоянных жалобах, как воздействуем на окружающих, и самое интересное в конце - пара советов для тех, кто любит поныть.

Пара цитат из статьи, которые кажутся важными:
👉 Повторяющиеся жалобы перестраивают ваш моз...</description><pubDate>Fri, 03 Jun 2022 07:26:55 GMT</pubDate><content:encoded>&lt;p&gt;📖 &lt;strong&gt;Пятничное чтиво&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/449854/&quot;&gt;Как жалобы перенастраивают ваш мозг на негатив&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Статья описывает, как мы меняемся при постоянных жалобах, как воздействуем на окружающих, и самое интересное в конце - пара советов для тех, кто любит поныть.&lt;/p&gt;
&lt;p&gt;Пара цитат из статьи, которые кажутся важными:
👉 Повторяющиеся жалобы перестраивают ваш мозг, чтобы сделать будущие жалобы более вероятными. Со временем, вы обнаруживаете что негативным быть легче, чем позитивным, независимо от того, что происходит вокруг вас. Нытье становится вашим поведением по умолчанию, и это влияет на то, как люди воспринимают вас.
👉 Жалобы нужно использовать, только для решения проблем, иначе пресекать их в зародыше.&lt;/p&gt;
&lt;p&gt;Скептически отношусь, к описываемым влияниям на мозг, но в целом статья довольно интересная.&lt;/p&gt;
&lt;p&gt;#fridayreading #нытьё&lt;/p&gt;</content:encoded></item><item><title>https://telegra.ph/Idealnyj-mir-dizajnerov-05-30</title><link>https://cherkashin.dev/posts/45/</link><guid isPermaLink="true">https://cherkashin.dev/posts/45/</guid><description>https://telegra.ph/Idealnyj-mir-dizajnerov-05-30</description><pubDate>Tue, 31 May 2022 07:00:08 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/Idealnyj-mir-dizajnerov-05-30&quot;&gt;https://telegra.ph/Idealnyj-mir-dizajnerov-05-30&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Автоматизированные бэкапы в Notion</title><link>https://cherkashin.dev/posts/44/</link><guid isPermaLink="true">https://cherkashin.dev/posts/44/</guid><description>Автоматизированные бэкапы в Notion

В конце апреля начали появляться сообщения, что некоторые русские аккаунты в Notion были заблокированы. Поддержка сперва подтвердила это, но в итоге сослалась на то, что они тестировали новый алгоритм и случайно заблокировали аккаунты, мол сейчас всё должно быть хорошо - продолжайте ...</description><pubDate>Tue, 24 May 2022 16:23:13 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Автоматизированные бэкапы в Notion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В конце апреля начали появляться сообщения, что некоторые русские аккаунты в Notion были заблокированы. Поддержка сперва подтвердила это, но в итоге сослалась на то, что они тестировали новый алгоритм и случайно заблокировали аккаунты, мол сейчас всё должно быть хорошо - продолжайте пользоваться. Но как тут спокойно пользовать после такого, сразу вспоминается фраза “мыши плакали, кололись, но продолжали жрать кактус”. Поэтому я решил настроить автоматизированные бэкапы.&lt;/p&gt;
&lt;p&gt;Для этого можно использовать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://artur-en.medium.com/automated-notion-backups-f6af4edc298d&quot;&gt;GitLab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Kla-w/notion-backup&quot;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Обе реализации используют один и тот же подход:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Для скачивания архива (тот же самый архив, который мы получаем &lt;a href=&quot;https://www.notion.so/help/back-up-your-data&quot;&gt;при ручном экспорте вокспейса&lt;/a&gt;) используется внутренний API Notion&lt;/li&gt;
&lt;li&gt;Для хранения бэкапов используется GitLab/GitHub репозиторий&lt;/li&gt;
&lt;li&gt;Скачанный архив разархивируется и пушится в репозиторий&lt;/li&gt;
&lt;li&gt;Для запуска бэкапа используется GitLab Pipeline/GitHub Actions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Я решил использовать GitHub. У меня много страниц с очень длинными названиями поэтому пайплайн валится при разархивировании. Я не стал заморачиваться и просто удалил разархивирование из пайплайна. Для меня это не так важно, ведь в любом случае ссылка на скачивание приходит на почту и хранится в течение 30 дней, поэтому если Notion заблокируют, я в любом случае смогу скачать бэкап.&lt;/p&gt;
&lt;p&gt;#notion&lt;/p&gt;</content:encoded></item><item><title>​​Интеграция Notion и Apple Shortcuts</title><link>https://cherkashin.dev/posts/43/</link><guid isPermaLink="true">https://cherkashin.dev/posts/43/</guid><description>​​Интеграция Notion и Apple Shortcuts

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

Например, пришла вам какая-то крутая идея — нужно её записать как можно ск...</description><pubDate>Tue, 10 May 2022 18:26:48 GMT</pubDate><content:encoded>&lt;p&gt;​​&lt;a href=&quot;https://telegra.ph/file/a82e69adfa06886c8d0a5.mp4&quot;&gt;&lt;strong&gt;Интеграция&lt;/strong&gt;&lt;/a&gt;** Notion и Apple Shortcuts**&lt;/p&gt;
&lt;p&gt;Одно из самых главных требований к личной системе планирования - очень простое/быстрое добавление задач. Вы должны делать это не задумываясь, иначе вы просто не будете записывать все ваши задачи и заметки.&lt;/p&gt;
&lt;p&gt;Например, пришла вам какая-то крутая идея — нужно её записать как можно скорее. Если процесс наполнения инбокса не прост как дважды два, вы просто забудете, что хотели записать.&lt;/p&gt;
&lt;p&gt;Сегодня настроил интеграцию Apple Shortcuts и Notion. Так как Siri поддерживает шорткаты, то заметки и задачи можно добавлять в ваш инбокс просто диктуя их Siri.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=EHdBHn960Ms&amp;#x26;ab_channel=PolyNome&quot;&gt;Using Siri to add to a Notion Database - Tutorial&lt;/a&gt; - Инструкция на Youtube&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.notion.so/Siri-Notion-Database-Tutorial-1257bae559044fe7a5e874207c230564&quot;&gt;Siri → Notion Database Tutorial&lt;/a&gt; - Инструкция в Notion&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#planning #notion #timemanagement&lt;/p&gt;</content:encoded></item><item><title>​​📖 Пятничное чтиво</title><link>https://cherkashin.dev/posts/42/</link><guid isPermaLink="true">https://cherkashin.dev/posts/42/</guid><description>​​📖 Пятничное чтиво

В статье &quot;Как быть более продуктивным, не заставляя себя&quot; есть следующая фраза

Есть группа людей, которые работают и получают от своей работы удовольствие. Давайте назовем этих людей деятелями. Под этим понятием мы не имеем в виду трудоголиков, которые не живут, а лишь работают целыми днями. У де...</description><pubDate>Fri, 06 May 2022 07:00:12 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/efa206ea3c0828941e2be.jpg&quot;&gt;​​&lt;/a&gt;📖 &lt;strong&gt;Пятничное чтиво&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В статье &lt;a href=&quot;https://habr.com/ru/company/vdsina/blog/554212/&quot;&gt;“Как быть более продуктивным, не заставляя себя”&lt;/a&gt; есть следующая фраза&lt;/p&gt;
&lt;p&gt;*Есть группа людей, которые работают и получают от своей работы удовольствие. Давайте назовем этих людей *деятелями*. Под этим понятием мы не имеем в виду трудоголиков, которые не живут, а лишь работают целыми днями. У деятелей здоровый баланс работы и отдыха. Что же особенного есть у них, чего нет у тех, кто ненавидит свою работу?&lt;/p&gt;
&lt;p&gt;В первую очередь, они по-другому относятся к работе.*&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Для них работа — это приятный цикл позитивной обратной связи. Деятели воспринимают работу как источник энергии и удовлетворения. С их точки зрения, работа позволяет им по-настоящему насладиться заслуженным отдыхом. Отдых делает их счастливее и мотивирует затем снова заняться работой.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Похоже именно работа позволяет мне по-настоящему насладиться отдыхом, в конце выходных обычно всегда появляется желание вернуться к работе.&lt;/p&gt;
&lt;p&gt;А это на прошлой неделе я был в Нижнем Новгороде, а сейчас замотивированный уже работаю.&lt;/p&gt;
&lt;p&gt;#fridayreading&lt;/p&gt;</content:encoded></item><item><title>Фраза недели</title><link>https://cherkashin.dev/posts/41/</link><guid isPermaLink="true">https://cherkashin.dev/posts/41/</guid><description>Фраза недели

Недавно посмотрел видео “Причина грыжи диска. Плавание и позвоночник.”, в котором была сказана очень интересная фраза:

«Однобокая нагрузка всегда будет вызывать перестройку организма в определённых местах, чтобы он, жертвуя чем-то, добивался спортивных результатов.» - фразу можно послушать здесь.

Неверо...</description><pubDate>Wed, 20 Apr 2022 07:00:14 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Фраза недели&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Недавно посмотрел видео “&lt;a href=&quot;https://m.youtube.com/watch?v=XSomxFo-13k&quot;&gt;Причина грыжи диска. Плавание и позвоночник&lt;/a&gt;.”, в котором была сказана очень интересная фраза:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;«Однобокая нагрузка всегда будет вызывать перестройку организма в определённых местах, чтобы он, жертвуя чем-то, добивался спортивных результатов.»&lt;/strong&gt; - фразу можно послушать &lt;a href=&quot;https://youtu.be/XSomxFo-13k&quot;&gt;здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Невероятное сходство можно проследить с процессами в команде или компании. Достаточно заменить, например “нагрузку” на “оценку работы” и “организм” на “процессы” — &lt;strong&gt;«Однобокая оценка работы всегда будет вызывать перестройку процессов в определённых местах, чтобы сотрудники, жертвуя чем-то, добивались поставленных целей.».&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Если в качестве метрик используется только количество закрытых задач и сделанных фич, то многие процессы в компании подстроятся, чтобы добиться необходимых результатов. Но придётся чем-то жертвовать:
● Будет меньше времени уделяться тестированию и написанию тестов
● На смену CodeReview придёт простое нажатие кнопки Approve или вовсе отмена обязательного ревью
● Будут исправляться симптомы, а не проблемы. Вряд ли кто-то будет докапываться до сути проблем, возникающих в продукте, поэтому будут появляться все новые и новые костыли
● Сотрудники перестанут помогать друг другу, ведь нужно закрыть как можно задач!&lt;/p&gt;
&lt;p&gt;Так же, как и со здоровьем, возможно, придется потратить очень много времени, чтобы исправить ситуацию и вылечить «процессы» в компании, ведь сотрудники по инерции будут следовать старым правилам.&lt;/p&gt;
&lt;p&gt;#weekphrase #processes&lt;/p&gt;</content:encoded></item><item><title>Пятничное чтиво - Interaction tests</title><link>https://cherkashin.dev/posts/40/</link><guid isPermaLink="true">https://cherkashin.dev/posts/40/</guid><description>Пятничное чтиво - Interaction tests

Недавно команда storybook добавила новую фичу - Interaction tests, поэтому в эту пятницу хочу порекомендовать к прочтению статью Test component interactions with Storybook, которая очень хорошо показывает преимущества по сравнению с jest тестами.

Немного проанализировав, для себя я...</description><pubDate>Fri, 08 Apr 2022 07:00:27 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Пятничное чтиво - Interaction tests&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Недавно команда storybook добавила новую фичу - Interaction tests, поэтому в эту пятницу хочу порекомендовать к прочтению статью &lt;a href=&quot;https://storybook.js.org/blog/test-component-interactions-with-storybook/&quot;&gt;Test component interactions with Storybook&lt;/a&gt;, которая очень хорошо показывает преимущества по сравнению с jest тестами.&lt;/p&gt;
&lt;p&gt;Немного проанализировав, для себя я смог выделить следующие преимущества и недостатки.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Преимущества:&lt;/strong&gt;
✅  Интерактивные тесты запускаются в реальном браузере и в связи с этим не имеют тех ограничений, &lt;a href=&quot;https://www.npmjs.com/package/jsdom#:~:text=Unimplemented%20parts%20of%20the%20web%20platform&quot;&gt;которые имеет JSDOM&lt;/a&gt;. Поэтому, например, мы можем проверять размеры элементов и их расположение относительно друг друга.
✅  Проще отлаживать тесты компонентов в браузере чем в консоли, ведь мы своими глазами видим причину падения тестов. Особенно это упрощает жизнь, если у вас есть мигающие тесты, падающие время от времени.
✅  Наличие &lt;a href=&quot;https://storybook.js.org/addons/@storybook/addon-interactions#:~:text=Experimental%20step%20debugging&quot;&gt;фичи пошаговой отладки&lt;/a&gt;, позволяет пошагово отлаживать тесты прямо в браузере без использования dev tools.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Недостатки:&lt;/strong&gt;
⚠️  Для запуска интерактивных тестов используется &lt;a href=&quot;https://playwright.dev/docs/intro&quot;&gt;playwright&lt;/a&gt;. &lt;a href=&quot;https://github.com/storybookjs/storybook/discussions/16861#discussioncomment-2513340&quot;&gt;Michael Shilman (член команды storybook) утверждает&lt;/a&gt;, что в настоящее время playwright тесты занимают в среднем на 30% больше времени, чем jest тесты. В то же время, команда storybook работает над разработкой своего &lt;a href=&quot;https://storybook.js.org/addons/@storybook/test-runner&quot;&gt;собственного тест-раннера&lt;/a&gt; и считает, что сможет добиться скорости выполнения тестов сравнимой с JSDOM.
⚠️ Тест-раннер работает только с запущенной версией storybook, поэтому помимо запуска тестов необходимо предварительно запустить storybook. Если storybook ещё не включен в ваш CI/CD pipeline — это также увеличит время работы pipeline’а.
⚠️ Storybook позволяет мокать &lt;a href=&quot;https://storybook.js.org/docs/react/writing-stories/build-pages-with-storybook#mocking-connected-components&quot;&gt;API запросы&lt;/a&gt;, но в целом всё ещё в значительной степени уступает &lt;code&gt;jest&lt;/code&gt;. Например, вы не сможете замокать код только для выбранных историй, или мокать код индивидуально для каждой выбранной истории.
⚠️ В данный момент интерактивные тесты не поддерживают test coverage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Напоследок, хотел бы отметить два момента:&lt;/strong&gt;
⚫️  Интерактивные тесты, не являются полной заменой jest - они предназначены лишь для тестирования компонентов и не подходит, например, для тестирования утилитных функций.
⚫️  Все перечисленные недостатки скорее всего будут со временем решены, так как релиз фичи состоялся не так давно, и команда storybook работает над её улучшением.&lt;/p&gt;
&lt;p&gt;#fridayreading #tests #storybook&lt;/p&gt;</content:encoded></item><item><title>Пятничное чтиво</title><link>https://cherkashin.dev/posts/39/</link><guid isPermaLink="true">https://cherkashin.dev/posts/39/</guid><description>Пятничное чтиво

Сегодня порекомендую доклад Алексея Катаева Рефакторинг: договариваемся, планируем, внедряем! Расшифровку можно почитать здесь.

Основные моменты:

Если у вас есть желание переписать всё с нуля, значит вы всё время добавляли новые и новые костыли и не рефакторилиЕсли в команде отсутствует культура рефа...</description><pubDate>Fri, 01 Apr 2022 07:01:12 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Пятничное чтиво&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Сегодня порекомендую доклад Алексея Катаева &lt;a href=&quot;https://www.youtube.com/watch?v=-yRyaN3XhMA&amp;#x26;t=105s&quot;&gt;Рефакторинг: договариваемся, планируем, внедряем&lt;/a&gt;! Расшифровку можно почитать &lt;a href=&quot;https://medium.com/@skyeng.blog/%D1%80%D0%B5%D1%84%D0%B0%D0%BA%D1%82%D0%BE%D1%80%D0%B8%D0%BD%D0%B3-%D0%B1%D0%B5%D0%B7-%D0%BE%D1%82%D1%80%D1%8B%D0%B2%D0%B0-%D0%BE%D1%82-%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%B0-%D0%BF%D1%8C%D0%B5%D1%81%D0%B0-%D0%B2-%D1%87%D0%B5%D1%82%D1%8B%D1%80%D0%B5%D1%85-%D0%BB%D0%B8%D1%86%D0%B0%D1%85-a7e3263aca5d&quot;&gt;здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Основные моменты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если у вас есть желание переписать всё с нуля, значит вы всё время добавляли новые и новые костыли и не рефакторили&lt;/li&gt;
&lt;li&gt;Если в команде отсутствует культура рефакторинга:
&lt;ul&gt;
&lt;li&gt;скорость разработки замедляется&lt;/li&gt;
&lt;li&gt;стабильность будет падать&lt;/li&gt;
&lt;li&gt;сложнее набирать новых разработчиков, ведь легаси дофига, а документации нифига&lt;/li&gt;
&lt;li&gt;как результат ⇒ бизнес теряет деньги&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Необходимо проводить непрерывный рефакторинг&lt;/li&gt;
&lt;li&gt;Чтобы убедить руководство в необходимости рефакторинга, необходимо договариваться, а не жаловаться. &lt;strong&gt;Нужны конкретные предложения вместо нытья&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Определять фронт работ (список областей для рефакторинга) должны все разработчики, а не только тимлид, ведь он наверняка не в курсе всех проблем в коде.&lt;/li&gt;
&lt;li&gt;С чего начать? Наверняка у каждого разработчика есть код, который он ненавидит всей душой, ведь после каждого изменения в этом коде он получает 5 новых багов. Можно начать с рефакторинга этих областей.&lt;/li&gt;
&lt;li&gt;Вести “Рефакторинг задачи” можно в вашем привычном таск трекере.&lt;/li&gt;
&lt;li&gt;“Рефакторинг задачи” должны описываться по определённому формату:
&lt;ul&gt;
&lt;li&gt;Проблема&lt;/li&gt;
&lt;li&gt;Профит&lt;/li&gt;
&lt;li&gt;Возможное решение&lt;/li&gt;
&lt;li&gt;Оценка по срокам&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Что с приоритетом? Как уже было сказано, разработчики лучше других знают приоритет, они и должны его выставлять.&lt;/li&gt;
&lt;li&gt;Выделить бюджет для рефакторинга, например 15% от времени спринта.&lt;/li&gt;
&lt;li&gt;Чтобы уменьшить количество нового технического долга, необходимо:
&lt;ul&gt;
&lt;li&gt;Заниматься ростом команды&lt;/li&gt;
&lt;li&gt;Шарить знания по проекту&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;По прошествии какого-то времени можно будет оценить количество технического долга и его рост.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#fridayreading #technicaldebt #planning #processes&lt;/p&gt;</content:encoded></item><item><title>Управление техническим долгом</title><link>https://cherkashin.dev/posts/38/</link><guid isPermaLink="true">https://cherkashin.dev/posts/38/</guid><description>Управление техническим долгом

На прошлой неделе задал вопрос об управлении техническим долгом Василию Половнёву  - Техническому директору в Бюро Горбунова.

Подскажи, как вы управляете техническим долгом и задачами, которые не связаны с разработкой продукта (обновление пакетных менеджеров (yarn 1 =&gt; pnpm), написание д...</description><pubDate>Tue, 29 Mar 2022 07:01:06 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Управление техническим долгом&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На прошлой неделе задал вопрос об управлении техническим долгом &lt;a href=&quot;https://t.me/polovnyov_journal&quot;&gt;Василию Половнёву&lt;/a&gt;  - Техническому директору в &lt;a href=&quot;https://bureau.ru/&quot;&gt;Бюро Горбунова&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Подскажи, как вы управляете техническим долгом и задачами, которые не связаны с разработкой продукта (обновление пакетных менеджеров (yarn 1 =&gt; pnpm), написание документации для старого кода, …) в Бюро?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;👉 Во-первых, мы на одной волне с бизнесом в этом вопросе: и мы, и ребята договорились о том, что техдолг — это плохо, это не дает нам запускать новые фичи быстрее. Если этот вопрос не решен, лучше начать с него. Иначе бизнесу будет казаться, что вы тратите время на какую-то фигню.
👉 Во-вторых, весь технический долг мы аккуратно записываем и периодически пересматриваем. Часто бывает, что какой-то должок вообще не нужно отдавать. А что-то вдруг начинает гореть прямо сейчас.
👉 В-третьих, мы берем продуктовый налог: 10-20% времени и внимания в итерации тратим на рефакторинг. Получается непрерывный рефакторинг в рамках итерации.
👉 В-четвертых, у нас есть &lt;a href=&quot;https://bureau.ru/bb/soviet/20150709/&quot;&gt;неделя после пуска&lt;/a&gt;. Это отдельная неделя сразу после пуска крупной (шестинедельной) фичи, которая тратится только на рефакторинг, доработки и горячие исправления. Эта неделя помогает выдохнуть, трезво оценить обстановку и заняться техдолгом. В &lt;a href=&quot;https://basecamp.com/handbook/09-how-we-work&quot;&gt;Бейскемпе эта же штука&lt;/a&gt; занимает две недели между циклами.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;А куда вы записываете тех долг, это тот же самый таск трекер, в котором ведутся обычные продуктовые задачи?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;👉 Да, это все в github issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;То есть перед началом нового спринта, вы так же, как и для продуктовых задач планируете какие задачи из технического долга необходимо закрыть?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;👉 Да, именно.&lt;/p&gt;
&lt;p&gt;Советую подписаться на телеграмм канал &lt;a href=&quot;https://t.me/polovnyov_journal&quot;&gt;Половнёв — Журнал&lt;/a&gt;, там есть много информации о разработке, тестировании и культуре работы.&lt;/p&gt;
&lt;p&gt;#planning #technicaldebt&lt;/p&gt;</content:encoded></item><item><title>Mock-функции в Jest</title><link>https://cherkashin.dev/posts/37/</link><guid isPermaLink="true">https://cherkashin.dev/posts/37/</guid><description>Mock-функции в Jest

В Jest существует 3 основные функции для подмены (мока) реализации:

jest.fn() - mock functionjest.spyOn().mock&lt;...&gt; - mock/spy functionmockResolvedValue()mockReturnValue()mockImplementation()jest.mock() - mock module

С первого взгляда может показаться не ясно, в каком случае следует применять ту ...</description><pubDate>Mon, 21 Mar 2022 07:00:36 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Mock-функции в Jest&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В Jest существует 3 основные функции для подмены (мока) реализации:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;jest.fn()&lt;/code&gt; - mock function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jest.spyOn().mock&amp;#x3C;...&gt;&lt;/code&gt; - mock/spy function
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mockResolvedValue()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mockReturnValue()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mockImplementation()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jest.mock()&lt;/code&gt; - mock module&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;С первого взгляда может показаться не ясно, в каком случае следует применять ту или иную функцию.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;jest.fn()&lt;/strong&gt; - самый простой способ создать mock-функцию. Функция используется в следующих случаях:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Тестируемая функция принимает в качестве аргумента другую функцию, которую мы можем подменить с помощью &lt;code&gt;jest.fn()&lt;/code&gt; - Dependency Injection&lt;/li&gt;
&lt;li&gt;Нам не важна предыдущая реализация и мы можем просто заменить её следующим образом &lt;code&gt;obj.func = jest.fn()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;jest.spyOn()&lt;/strong&gt; заменяет начальную реализацию шпионом, что позволяет нам отслеживать вызовы функции. При этом, по умолчанию реализация не изменяется, если необходимо изменить реализацию, это можно сделать следующим образом: &lt;code&gt;spyOn(obj, ‘func’).mockImplementation(() =&gt; “mocked value”)&lt;/code&gt;. Функция используется в следующих случаях:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Необходимо отслеживать вызовы функции без подмены реализации&lt;/li&gt;
&lt;li&gt;Необходимо подменить зависимость, которая используется внутри тестируемой функции и не передаётся в качестве параметров&lt;/li&gt;
&lt;li&gt;Необходимо подменить реализацию для отдельного теста/группы тестов и восстановить оригинальную реализацию для остальных &lt;code&gt;mockedFunc.mockRestore&lt;/code&gt;
&lt;a href=&quot;https://stackoverflow.com/questions/64930286/why-use-spyon-with-mock-implemenation-rather-than-jest-fn&quot;&gt;Why use spyon with mock implemenation rather than jest.fn&lt;/a&gt;? - хороший пример, описывающий ситуацию, в которой лучше использовать &lt;code&gt;jest.spyOn()&lt;/code&gt; вместо &lt;code&gt;jest.fn()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;jest.mock()&lt;/strong&gt;. В отличие от функций &lt;code&gt;jest.fn()&lt;/code&gt; и &lt;code&gt;jest.spyOn()&lt;/code&gt;, функция &lt;code&gt;jest.mock()&lt;/code&gt; - заменяет не отдельную функцию, а весь модуль. Функция используется в следующих случаях:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Необходимо подменить все экспортируемые функции модуля&lt;/li&gt;
&lt;li&gt;Необходимо подменить часть экспортируемых функций модуля
Недостаток функции &lt;code&gt;jest.mock&lt;/code&gt; в том, что она не позволяет восстановить оригинальную реализацию, для таких случаев лучше использовать &lt;code&gt;jest.spyOn&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ещё по теме&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@rickhanlonii/understanding-jest-mocks-f0046c68e53c#734c&quot;&gt;Understanding Jest Mocks&lt;/a&gt; - подробно описывает каждую рассмотренную функцию с примерами&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jestjs.io/docs/mock-functions&quot;&gt;Mock Functions&lt;/a&gt; и &lt;a href=&quot;https://jestjs.io/docs/es6-class-mocks&quot;&gt;ES6 Class Mocks&lt;/a&gt; - официальная документация jest&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#frontend #tests #jest&lt;/p&gt;</content:encoded></item><item><title>Настройка VPN</title><link>https://cherkashin.dev/posts/36/</link><guid isPermaLink="true">https://cherkashin.dev/posts/36/</guid><description>Настройка VPN

В связи с последними событиями, сайты начинают блокировать доступ для российских пользователей. Например &lt;pnpm.io&gt; сейчас не доступен из России.  Также было создано ишью на гитхабе для ограничения доступа к сайту для российских пользователей.

Есть вероятность, что и наше правительство начнёт &quot;замедлять&quot;...</description><pubDate>Thu, 03 Mar 2022 07:00:43 GMT</pubDate><content:encoded>&lt;p&gt;**Настройка VPN&lt;/p&gt;
&lt;p&gt;**В связи с последними событиями, сайты начинают блокировать доступ для российских пользователей. Например &amp;#x3C;pnpm.io&gt; сейчас не доступен из России.  Также было создано &lt;a href=&quot;https://github.com/github/feedback/discussions/12042&quot;&gt;ишью на гитхабе&lt;/a&gt; для ограничения доступа к сайту для российских пользователей.&lt;/p&gt;
&lt;p&gt;Есть вероятность, что и наше правительство начнёт “замедлять” и блокировать сайты/приложения, где может размещаться “нежелательная” на их взгляд информация:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Instagram&lt;/li&gt;
&lt;li&gt;Facebook&lt;/li&gt;
&lt;li&gt;Twitter&lt;/li&gt;
&lt;li&gt;YouTube&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Поэтому самое время настроить VPN (напрмер, &lt;a href=&quot;https://psiphon3.com/ru/index.html&quot;&gt;pshiphon&lt;/a&gt;) или установить &lt;a href=&quot;https://www.torproject.org/&quot;&gt;TorBrowser&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Почему CSS называется каскадными таблицами стилей?</title><link>https://cherkashin.dev/posts/35/</link><guid isPermaLink="true">https://cherkashin.dev/posts/35/</guid><description>Почему CSS называется каскадными таблицами стилей?

Каскад — это алгоритм, который определяет, как вычислить результирующие стили элементов на основе CSS правил, объявленных в различных источниках.

CSS правила могут быть объявлены в следующих источниках:

User-agent stylesheets (Браузерные стили) - дефолтные стили бра...</description><pubDate>Tue, 15 Feb 2022 07:00:57 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Почему CSS называется &lt;em&gt;каскадными&lt;/em&gt;&lt;/strong&gt; **таблицами стилей?&lt;/p&gt;
&lt;p&gt;Каскад** — это алгоритм, который определяет, как вычислить результирующие стили элементов на основе CSS правил, объявленных в различных источниках.&lt;/p&gt;
&lt;p&gt;CSS правила могут быть объявлены в следующих источниках:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade#user-agent_stylesheets&quot;&gt;User-agent stylesheets&lt;/a&gt; (Браузерные стили) - дефолтные стили браузера, обычно мы сбрасываем их с помощью CSS Reset&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade#author_stylesheets&quot;&gt;Author stylesheets&lt;/a&gt; (Авторские стили) - Стили задаваемые разработчиками, именно эти стили и пишем мы с вами.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade#user_stylesheets&quot;&gt;User stylesheets&lt;/a&gt; (Пользовательские) - стили, которые могут применять к нашему сайту обычные пользователи. Возможно когда-то, вы видели, как кто-то использует их, чтобы задать кастомный вид для ВК.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;То есть, для применения стилей, браузеру необходимо знать не только специфичность правила, но и источник этих правил, ведь у них тоже есть свой приоритет:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Авторские/Правила разработчиков - **самый приоритетный
**2. Пользовательские&lt;/li&gt;
&lt;li&gt;Браузерные стили&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;При применении &lt;code&gt;!important&lt;/code&gt; всё становится с ног на голову и приоритеты меняются следующим образом:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Браузерные стили с &lt;code&gt;!important&lt;/code&gt; - **самый приоритетный
**2. Пользовательские с &lt;code&gt;!important &lt;/code&gt;3. Авторские/Правила разработчиков `!important&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;`Таким образом, &lt;strong&gt;алгоритм каскада&lt;/strong&gt; выглядит вот так:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Найти стили из различных ресурсов, которые применимы к данному элементу&lt;/li&gt;
&lt;li&gt;Выбрать источник с наибольшим приоритетом (важен именно приоритет источника, специфичность всё ещё не учитывается)&lt;/li&gt;
&lt;li&gt;В ход идёт алгоритм специфичности, чтобы выбрать свойство с наибольшим весом&lt;/li&gt;
&lt;li&gt;Если специфичность нескольких правил равна, в результате берётся то значение, которое объявлено позже&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;**Вывод
**Для понимания тема кажется полезной, но на практике ваши стили всегда будут перебивать браузерные стили, а пользовательские стили поддерживаются всё меньше:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://codereview.chromium.org/64843004&quot;&gt;Поддержка в хроме удалена в 2013 году&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://davidwalsh.name/firefox-user-stylesheet&quot;&gt;В Firefox поддержка по-умолчанию выключена&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**Примеры
**- &lt;a href=&quot;https://drafts.csswg.org/css-cascade/#importance&quot;&gt;CSS Cascading and Inheritance Level 4 - Example 18&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade#example&quot;&gt;Introducing the CSS Cascade - Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**Ещё по теме
**- &lt;a href=&quot;https://doka.guide/css/cascade/&quot;&gt;Дока - принцип каскада&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://doka.guide/css/specificity/&quot;&gt;Дока - специфичность&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade&quot;&gt;MDN - Introducing the CSS Cascade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://drafts.csswg.org/css-cascade/#cascading&quot;&gt;CSS Cascading and Inheritance Level 4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://t.me/polovnyov_journal/155&quot;&gt;CSS Reset в 2021&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;#css #web&lt;/p&gt;</content:encoded></item><item><title>Пятничное чтиво</title><link>https://cherkashin.dev/posts/34/</link><guid isPermaLink="true">https://cherkashin.dev/posts/34/</guid><description>Пятничное чтиво

Сегодня порекомендую всего одну статью. Она мне напоминает меня самого, ведь я допускал и возможно всё ещё допускаю те же ошибки. Я довольно часто отчаянно отстаивал свою позицию (даже в не значимых моментах) и считал, что это нормально. Представьте моё удивление, когда я узнал, что мои коллеги считают...</description><pubDate>Fri, 04 Feb 2022 07:00:54 GMT</pubDate><content:encoded>&lt;p&gt;**Пятничное чтиво&lt;/p&gt;
&lt;p&gt;**Сегодня порекомендую всего одну статью. Она мне напоминает меня самого, ведь я допускал и возможно всё ещё допускаю те же ошибки. Я довольно часто отчаянно отстаивал свою позицию (даже в не значимых моментах) и считал, что это нормально. Представьте моё удивление, когда я узнал, что мои коллеги считают меня агрессивным 😅.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/558858/&quot;&gt;Как меня чуть не уволили из-за токсичного поведения и что было дальше&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;После прочтения статьи подумайте, не допускаете ли вы тех же ошибок, что я и автор.&lt;/p&gt;
&lt;p&gt;#fridayreading #article&lt;/p&gt;</content:encoded></item><item><title>Прокси-серве для Яндекс.Музыки</title><link>https://cherkashin.dev/posts/33/</link><guid isPermaLink="true">https://cherkashin.dev/posts/33/</guid><description>Прокси-серве для Яндекс.Музыки

Прошлой весной начал разбираться с OpenAPI и решил написать схему для Яндекс.Музыки. Проблема была лишь в том, что из-за CORS нормально пользоваться сгенерированной документацией невозможно. Чтобы отключить CORS в хроме приходилось запускать его с флагом -disable-web-security.

Решение с...</description><pubDate>Mon, 31 Jan 2022 07:00:56 GMT</pubDate><content:encoded>&lt;p&gt;**Прокси-серве для Яндекс.Музыки&lt;/p&gt;
&lt;p&gt;**Прошлой весной начал разбираться с OpenAPI и решил написать &lt;a href=&quot;https://github.com/acherkashin/yandex-music-open-api&quot;&gt;схему для Яндекс.Музыки&lt;/a&gt;. Проблема была лишь в том, что из-за CORS нормально пользоваться сгенерированной документацией невозможно. Чтобы отключить CORS в хроме приходилось запускать его с флагом &lt;code&gt;-disable-web-security&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Решение скажем честно - не очень 👎. Правильным решением будет написание прокси-сервера, на котором были бы разрешены кросдоменные запросы. Другими словами, вместо того, чтобы напрямую обращаться к серверу Я.Музыки, на котором запрещены крос-доменные запросы, мы обращаемся к прокси-серверу, который перенапрявляет все наши вопросы к Я.Музыке и возвращает нам ответ. Так как CORS, есть только в браузере, то мы свободно отправляем запросы с нашего прокси сервера на сервер Я.Музыки.&lt;/p&gt;
&lt;p&gt;Собственно, вчера я и написал &lt;a href=&quot;https://github.com/acherkashin/yandex-music-cors-proxy&quot;&gt;такой прокси-сервер&lt;/a&gt; на основе библиотеки &lt;a href=&quot;https://github.com/Rob--W/cors-anywhere&quot;&gt;cors-anywhere&lt;/a&gt; и захостить его на хероку (&lt;a href=&quot;https://yandex-music-cors-proxy.herokuapp.com/&quot;&gt;https://yandex-music-cors-proxy.herokuapp.com/&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Теперь все запросы можно проксировать следующим образом: `&lt;a href=&quot;https://yandex-music-cors-proxy.herokyapp.com/&quot;&gt;https://yandex-music-cors-proxy.herokyapp.com/&lt;/a&gt;&lt;any-url&gt;&lt;/any-url&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Например: &lt;/code&gt;&lt;a href=&quot;https://yandex-music-cors-proxy.herokuapp.com/https://api.music.yandex.net:443/users/541320800/playlists/list&quot;&gt;https://yandex-music-cors-proxy.herokuapp.com/https://api.music.yandex.net:443/users/541320800/playlists/list&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;`Ресурсы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/acherkashin/yandex-music-cors-proxy&quot;&gt;Исходники прокси сервера
&lt;/a&gt;- &lt;a href=&quot;https://github.com/acherkashin/yandex-music-open-api&quot;&gt;Исходники OpenAPI-схемы Я.Музыки
&lt;/a&gt;- [OpenAPI документация Я.Музыки&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;](&lt;a href=&quot;https://www.cherkashin.dev/yandex-music-open-api/)%D0%95%D1%89%D1%91&quot;&gt;https://www.cherkashin.dev/yandex-music-open-api/)Ещё&lt;/a&gt; по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Rob--W/cors-anywhere&quot;&gt;cors-anywere
&lt;/a&gt;- &lt;a href=&quot;https://devcenter.heroku.com/articles/getting-started-with-nodejs?singlepage=true#deploy-the-app&quot;&gt;Getting Started on Heroku with Node.js
&lt;/a&gt;- [GitHub Integration (Heroku GitHub Deploys)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;](&lt;a href=&quot;https://devcenter.heroku.com/articles/github-integration)#yandexmusic&quot;&gt;https://devcenter.heroku.com/articles/github-integration)#yandexmusic&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Наращивание специфичности</title><link>https://cherkashin.dev/posts/32/</link><guid isPermaLink="true">https://cherkashin.dev/posts/32/</guid><description>Наращивание специфичности

Вчера на сайте доки читал о специфичности в CSS и наткнулся на интересный трюк. Он кажется достаточно элементарным, но никогда не приходил мне в голову. Чтобы увеличить специфичность, можно использовать один и тот же класс, в рамках одного селектора несколько раз. Вот для наглядности небольшо...</description><pubDate>Thu, 27 Jan 2022 07:01:18 GMT</pubDate><content:encoded>&lt;p&gt;**Наращивание специфичности&lt;/p&gt;
&lt;p&gt;**Вчера на &lt;a href=&quot;https://doka.guide/&quot;&gt;сайте доки&lt;/a&gt; читал о специфичности в CSS и наткнулся на &lt;a href=&quot;https://doka.guide/css/specificity/#vadim-makeev&quot;&gt;интересный трюк&lt;/a&gt;. Он кажется достаточно элементарным, но никогда не приходил мне в голову. &lt;strong&gt;Чтобы увеличить специфичность, можно использовать один и тот же класс, в рамках одного селектора несколько раз.&lt;/strong&gt; Вот для наглядности небольшой пример:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;css&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.button&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;// как я бы сделал раньше&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.button.fancy-button&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;// трюк&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;.fancy-button.fancy-button&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;```Возможно, такие селекторы кажутся странными, поэтому я бы добавил поясняющий комментарий в коде для других разработчиков и пояснил, что именно я здесь делаю.&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;Такой приём может оказаться полезен, когда вы используете библиотеки компонентов вроде [&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;material-ui&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;](https://mui.com/) и не хотите завязываться на CSS классы, предоставляемые библиотекой, для увеличения специфичности. &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;#css&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content:encoded></item><item><title>​​Пятничное чтиво</title><link>https://cherkashin.dev/posts/31/</link><guid isPermaLink="true">https://cherkashin.dev/posts/31/</guid><description>​​Пятничное чтиво

Всю эту неделю освежал в памяти как работает Event Loop (Событийный цикл) в JavaScript и всё что с ним связано. Ссылки ниже помогут ответить на вопросы:

❓Что такое микротаски
❓Что такое макротаски/таски
❓Что такое web api
❓В какой момент выполняются макро- и микротаски и по сколько за раз
❓Какая осн...</description><pubDate>Fri, 21 Jan 2022 07:00:53 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/d5ceb7fb0ccfff8c7730c.jpg&quot;&gt;​​&lt;/a&gt;**Пятничное чтиво&lt;/p&gt;
&lt;p&gt;**Всю эту неделю освежал в памяти как работает Event Loop (Событийный цикл) в JavaScript и всё что с ним связано. Ссылки ниже помогут ответить на вопросы:&lt;/p&gt;
&lt;p&gt;❓Что такое микротаски
❓Что такое макротаски/таски
❓Что такое web api
❓В какой момент выполняются макро- и микротаски и по сколько за раз
❓Какая основная задача EventLoop&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8aGhZQkoFbQ&amp;#x26;t=243s&quot;&gt;What the heck is the event loop anyway? | Philip Roberts | JSConf EU
&lt;/a&gt;- &lt;a href=&quot;https://www.jsv9000.app/&quot;&gt;JavaScript Visualizer 9000&lt;/a&gt; - event loop visualizer&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif&quot;&gt;JavaScript Visualized: Event Loop
&lt;/a&gt;- &lt;a href=&quot;https://learn.javascript.ru/event-loop&quot;&gt;Современный учебник JavaScript: Событийный цикл: микрозадачи и макрозадачи
&lt;/a&gt;- &lt;a href=&quot;https://habr.com/ru/post/461401/&quot;&gt;Что ты такое, Event Loop? Или как устроен цикл событий в браузере Chrome
&lt;/a&gt;- &lt;a href=&quot;https://www.youtube.com/watch?v=bUx8wk4LdoY&quot;&gt;Иван Тулуп: асинхронщина в JS под капотом / Михаил Башуров (Luxoft)
&lt;/a&gt;- [Jake Archibald - Tasks, microtasks, queues and schedules&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;](&lt;a href=&quot;https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)#fridayreading&quot;&gt;https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)#fridayreading&lt;/a&gt; #javascript #eventloop&lt;/p&gt;</content:encoded></item><item><title>Очередная история о борьбе с выгоранием</title><link>https://cherkashin.dev/posts/29/</link><guid isPermaLink="true">https://cherkashin.dev/posts/29/</guid><description>Очередная история о борьбе с выгоранием

Последний месяц я пытался собрать все приёмы, которые использовал, чтобы улучшить своё состояние и зарубить выгорание на корню. Собрал всё, от собственных выводов и наблюдений до советов из &quot;Gettings Things Done&quot; и советов твиттерских. Оформил всё в статью и опубликовал на хабр....</description><pubDate>Thu, 30 Dec 2021 07:00:38 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Очередная история о борьбе с выгоранием&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Последний месяц я пытался собрать все приёмы, которые использовал, чтобы улучшить своё состояние и зарубить выгорание на корню. Собрал всё, от собственных выводов и наблюдений до советов из “Gettings Things Done” и советов твиттерских. Оформил всё в статью и опубликовал на хабр.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://habr.com/ru/post/598517/&quot;&gt;https://habr.com/ru/post/598517/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#burnout&lt;/p&gt;</content:encoded></item><item><title>Очередная история о борьбе с выгоранием</title><link>https://cherkashin.dev/articles/fighting-burnout-story/</link><guid isPermaLink="true">https://cherkashin.dev/articles/fighting-burnout-story/</guid><description>Я думаю, не стоит никому объяснять, что такое выгорание, большинство периодически ходят по краю, рискуя упасть и окунуться в это состояние с головой. В двух словах выгорание — это поломка системы восстановления энергии в условиях продолжительного стресса.</description><pubDate>Wed, 29 Dec 2021 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/fighting-burnout-story/article-logo.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/fighting-burnout-story/article-logo.png"/></item><item><title>Фраза недели - &quot;Когда ты испытываешь гнев, отчаяние и готов заплакать, значит тебе не хватает софт…</title><link>https://cherkashin.dev/posts/28/</link><guid isPermaLink="true">https://cherkashin.dev/posts/28/</guid><description>Фраза недели - &quot;Когда ты испытываешь гнев, отчаяние и готов заплакать, значит тебе не хватает софт скилов&quot;

Софт скилы также важны как хард скилы. Что такое софт скилы?  Все, что помогает вам сделать вашу работу лучше и не связано непосредственно с программированием:

переговорыпланированиесамоорганизациястрессоустойчи...</description><pubDate>Sat, 18 Dec 2021 11:12:17 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Фраза недели&lt;/strong&gt; - “Когда ты испытываешь гнев, отчаяние и готов заплакать, значит тебе не хватает софт скилов”&lt;/p&gt;
&lt;p&gt;Софт скилы также важны как хард скилы. Что такое софт скилы?  Все, что помогает вам сделать вашу работу лучше и не связано непосредственно с программированием:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;переговоры&lt;/li&gt;
&lt;li&gt;планирование&lt;/li&gt;
&lt;li&gt;самоорганизация&lt;/li&gt;
&lt;li&gt;стрессоустойчивость&lt;/li&gt;
&lt;li&gt;и т.д.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ситуация 1&lt;/strong&gt;: В вашем проекте творится хаос, каждый пишет так, как он хочет, линтеры отсутствуют. Казалось бы, нужно просто добавить линтер, и это решит большую часть проблем. Но какие правила должен содержать линтер? А может кто-то вообще не понимает зачем он нужен «ведь и так сойдёт»? Поэтому в первую очередь вам придётся &lt;strong&gt;донести до команды&lt;/strong&gt; важность использования линтера и &lt;strong&gt;договориться&lt;/strong&gt; о наборе правил, который бы устраивал всех.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ситуация 2&lt;/strong&gt;: Вы руководите командой разработчиков. Вы делегировали одну из задач, проходит месяц, но прогресса по задаче очень мало, а дедлайн близок. Конечно, в этой ситуации вас могут спасти хард скилы, и вы можете вывезти задачу на себе. Но где гарантии, что эта ситуация не повторится снова? Гораздо лучше &lt;strong&gt;проанализировать&lt;/strong&gt; сложившуюся ситуацию, &lt;strong&gt;понять&lt;/strong&gt; почему это произошло и &lt;strong&gt;изменить процессы&lt;/strong&gt; в команде таким образом, чтобы предотвратить подобные проблемы в дальнейшем.&lt;/p&gt;
&lt;p&gt;#weekphrase #softskills&lt;/p&gt;</content:encoded></item><item><title>Несколько приёмов, которые я использую, чтобы улучшить своё эмоциональное состояние и не выгореть:</title><link>https://cherkashin.dev/posts/27/</link><guid isPermaLink="true">https://cherkashin.dev/posts/27/</guid><description>Несколько приёмов, которые я использую, чтобы улучшить своё эмоциональное состояние и не выгореть:

🎈 Первое и самое главное. Я создал для себя внешнее хранилище информации, которое содержит, всё, что для меня важно: все мои задачи, планы, проекты, заметки, планы путешествий. Основная задача нашего мозга - генерация р...</description><pubDate>Wed, 08 Dec 2021 07:01:08 GMT</pubDate><content:encoded>&lt;p&gt;Несколько приёмов, которые я использую, чтобы улучшить своё эмоциональное состояние и не выгореть:&lt;/p&gt;
&lt;p&gt;🎈 Первое и самое главное. &lt;strong&gt;Я создал для себя внешнее хранилище информации&lt;/strong&gt;, которое содержит, всё, что для меня важно: все мои задачи, планы, проекты, заметки, планы путешествий. Основная задача нашего мозга - генерация различных идей, но он совершенно не предназначен для хранения информации. Важно избавиться от стресса, который вы чувствуете, из-за того, что вам кажется, что вы что-то забыли.&lt;/p&gt;
&lt;p&gt;🎈 &lt;strong&gt;Спать по 7-8 часов в день.&lt;/strong&gt; Ваша голова не сможет нормально работать без полноценного отдыха, поэтому нет смысла засиживаться допоздна.&lt;/p&gt;
&lt;p&gt;🎈 &lt;strong&gt;Не считать проблемы компании своими проблемами.&lt;/strong&gt; Если вам нужно перерабатывать, скорее всего вы закрываете чью-то некомпетентность в компании. Не наняли новых сотрудников, облажались с дедлайнами, не налажены процессы. Ассоциация проблем компании со своими проблемами - прямой путь к выгоранию, ведь в этом случае стресс ощущается более остро в тяжелых ситуациях.&lt;/p&gt;
&lt;p&gt;🎈 &lt;strong&gt;Не перерабатывать.&lt;/strong&gt; На самом деле, в большинстве случаев это просто бессмысленно, давайте будем честны, на работе мы меняем своё время на деньги. Нет ничего плохого, чтобы защищать своё время. Начальство всегда хочет, чтобы вы работали больше.&lt;/p&gt;
&lt;p&gt;🎈 &lt;strong&gt;Вы не должны ничего заслуживать.&lt;/strong&gt; Нет ничего зазорного в том, чтобы побездельничать и посмотреть Youtube. Чувствовать себя хорошо — это нормально. В прошлом я был на 100% уверен, что я должен пахать круглые сутки.&lt;/p&gt;
&lt;p&gt;🎈 &lt;strong&gt;Не взваливать на себя больше, чем можешь сделать.&lt;/strong&gt; Раньше я пытался каждую минуту проводить с пользой. Едешь в маршрутке - учишь английский, ложишься спать и засыпаешь под подкаст. И раз за разом ты оказываешься на грани выгорания. В один день ты просто перестаёшь делать ВСЁ. Нужно помнить, что наша жизнь — это марафон, а не спринт и нужно правильно распределять силы.&lt;/p&gt;
&lt;p&gt;🎈 &lt;strong&gt;Уметь говорить “нет”.&lt;/strong&gt; Это очень заезженная фраза, но она действительно работает. Мы привыкли взваливать на себя всё подряд и соглашаться на любые просьбы. Если кто-то из друзей или знакомых просит вас о чём-нибудь, и у вас действительно нет времени на это, нет ничего плохого в том, чтобы сказать “нет”. Конечно, нужно понимать, что просьбы бывают разные, но не нужно отодвигать свои интересы на второй план, боясь кого-то обидеть.&lt;/p&gt;
&lt;p&gt;А какие приёмы используете вы?&lt;/p&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/iamlerun/status/1452548274855022596?s=21&quot;&gt;Лера Зелёная. Вредные советы, как довести себя до истощения работой на три, два, раз.
&lt;/a&gt;- &lt;a href=&quot;https://twitter.com/itunderhood/status/1456544319884697624&quot;&gt;Человек из IT. О переработках.
&lt;/a&gt;- [Человек из IT. Тред заботы о себе.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;](&lt;a href=&quot;https://twitter.com/itunderhood/status/1380897965552898050)#burnout&quot;&gt;https://twitter.com/itunderhood/status/1380897965552898050)#burnout&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>​​Сегодня поговорим немного об обучении</title><link>https://cherkashin.dev/posts/26/</link><guid isPermaLink="true">https://cherkashin.dev/posts/26/</guid><description>​​Сегодня поговорим немного об обучении

У меня часто бомбит, когда друзья рассказывают, как их учат в универе. О том как от них требуют, чтобы все лекции должны быть обязательно написаны, что нужно ходить на все пары без пропусков и ... можно приводить ещё кучу примеров. Я думаю, у каждого был такой опыт. Больше всего...</description><pubDate>Thu, 02 Dec 2021 07:01:08 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/c547121501554bc8e4b0d.jpg&quot;&gt;​​&lt;/a&gt;**Сегодня поговорим немного об обучении&lt;/p&gt;
&lt;p&gt;**У меня часто бомбит, когда друзья рассказывают, как их учат в универе. О том как от них требуют, чтобы все лекции должны быть обязательно написаны, что нужно ходить на все пары без пропусков и … можно приводить ещё кучу примеров. Я думаю, у каждого был такой опыт. Больше всего раздражает, когда в тебя впихивают знания и не объясняют, как они тебе пригодятся, почему я должен это всё учить, а не просто забить на пары?&lt;/p&gt;
&lt;p&gt;В общем, к чему я тут распинаюсь. Последние 3 недели я проходил курс “Наставник” от Яндекс.Практикума, где объясняли основные правила коммуникации и взаимодействия со студентами. Я думаю, если бы каждый преподаватель в своё время прошёл такой курс с нашей системой образования всё было бы гораздо лучше. Ну хватит о преподавании и университетах. В целом курс достаточно универсальный и будет полезен любому. Если вы работаете в команде вы наверняка:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Общаетесь с коллегами&lt;/li&gt;
&lt;li&gt;Передаёте знания&lt;/li&gt;
&lt;li&gt;Проводите код ревью&lt;/li&gt;
&lt;li&gt;Проводите образовательные сессии
и чтобы всё это успешно делать необходимы софт скиллы, которые и прокачиваются на курсе.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ну и давайте кратко опишу курс. Курс состоял из 5 занятий, каждое из которых содержало:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;теорию&lt;/li&gt;
&lt;li&gt;практику&lt;/li&gt;
&lt;li&gt;домашку.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;С теорией и домашкой всё более и менее понятно, но самое крутое, что было на курсе - отработки. Не те отработки, на которые вы ходили, если пропустили пару или не сделали домашку 😁.  На каждой практике было порядка трёх отработок, на которых мы тренировались отработать реальные ситуации, которые могут произойти во время преподавания в Практикуме.&lt;/p&gt;
&lt;p&gt;Подробнее можете почитать на &lt;a href=&quot;https://practicum.yandex.ru/promo/mentors-school&quot;&gt;официальном сайте&lt;/a&gt;, следующий набор уже в 2022 году.&lt;/p&gt;</content:encoded></item><item><title>Фраза недели - &quot;Лучшее - враг хорошего&quot;</title><link>https://cherkashin.dev/posts/25/</link><guid isPermaLink="true">https://cherkashin.dev/posts/25/</guid><description>Фраза недели - &quot;Лучшее - враг хорошего&quot;

На мой взгляд эта фраза отлично описывает одновременно и &quot;синдром самозванца&quot;, и &quot;перфекционизм&quot; (а соответственно и меня 😀).

▪️Как часто вы брались за что-то, но не доводили до конца, потому что это было &quot;недостаточно хорошо&quot; сделано?
▪️Какое вы вообще имеете право кого-то уч...</description><pubDate>Mon, 29 Nov 2021 07:00:53 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Фраза недели&lt;/strong&gt; - “Лучшее - враг хорошего”&lt;/p&gt;
&lt;p&gt;На мой взгляд эта фраза отлично описывает одновременно и “синдром самозванца”, и “перфекционизм” (а соответственно и меня 😀).&lt;/p&gt;
&lt;p&gt;▪️Как часто вы брались за что-то, но не доводили до конца, потому что это было “недостаточно хорошо” сделано?
▪️Какое вы вообще имеете право кого-то учить?
▪️Ведь у вас недостаточно опыта!
▪️Вам нужно изучить все ресурсы в интернете, чтобы не дай бог не допустить ни малейшей ошибки!&lt;/p&gt;
&lt;p&gt;Я постоянно начинаю писать заметки, статьи и стараюсь сделать это идеально. И знаете, что происходит в итоге? Ничего! Всё это идёт в стол! Вместо того, чтобы сделать что-то “достаточно хорошо”, в погоне за идеалом, я не делаю это никак. Вместо того, чтобы просто написать о своём опыте, я считаю, что мне нужно перерыть весь интернет, проконсультироваться с кем-то из коллег и всё 100 раз перепроверить. В итоге, всё это раздувается настолько, что я просто забиваю ещё в самом начале.&lt;/p&gt;
&lt;p&gt;Ну и какой вывод из всего этого. Лучше сделать, что-то “достаточно хорошо”, чем стараться сделать это идеально, иначе вы рискуете не сделать этого совсем никак. Конечно, вы можете облажаться, но все ведь ошибаются, верно? Лучше облажаться, чем всю жизнь думать о чём-то и никогда не сделать. Ну и как говорил Мирон,  “Сколько себя помню я дрожал над репутацией, но, чтобы стать свободнее нужно не бояться обосраться.” 😉.&lt;/p&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://habr.com/ru/post/548384/&quot;&gt;Синдром самозванца у айтишников. Немного логики для тех, кто подумывает писать в блоги
&lt;/a&gt;- [Барух Садогурский - Как правильно продать себя ради фана и профита - Синдром Самозванца&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;](&lt;a href=&quot;https://youtu.be/sEexbEv2iGc?t=1015)#weekphrase&quot;&gt;https://youtu.be/sEexbEv2iGc?t=1015)#weekphrase&lt;/a&gt; #perfectionism #impostorsyndrome&lt;/p&gt;</content:encoded></item><item><title>Пятничное чтиво.</title><link>https://cherkashin.dev/posts/24/</link><guid isPermaLink="true">https://cherkashin.dev/posts/24/</guid><description>Пятничное чтиво.

Ссылки о Code Review, которые расскажут:

👉 для чего он необходим
👉 какие проблемы решает
👉 как его необходимо проводить
👉 на что смотреть во время код ревью
👉 как указывать на недостатки в коде и не поссориться с коллегами
👉 и многое другое

Why code reviews matter (and actually save time!)
- F...</description><pubDate>Fri, 22 Oct 2021 07:01:22 GMT</pubDate><content:encoded>&lt;p&gt;**Пятничное чтиво.&lt;/p&gt;
&lt;p&gt;**Ссылки о Code Review, которые расскажут:&lt;/p&gt;
&lt;p&gt;👉 для чего он необходим
👉 какие проблемы решает
👉 как его необходимо проводить
👉 на что смотреть во время код ревью
👉 как указывать на недостатки в коде и не поссориться с коллегами
👉 и многое другое&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.atlassian.com/agile/software-development/code-reviews&quot;&gt;Why code reviews matter (and actually save time!)
&lt;/a&gt;- &lt;a href=&quot;https://dev.to/dangoslen/four-ways-to-leave-a-bad-code-review-5gkn&quot;&gt;Four Ways to Leave a Bad Code Review
&lt;/a&gt;- &lt;a href=&quot;https://medium.com/javascript-scene/the-outrageous-cost-of-skipping-tdd-code-reviews-57887064c412&quot;&gt;The Outrageous Cost of Skipping TDD &amp;#x26; Code Reviews
&lt;/a&gt;- [Google Engineering Practices Documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;](&lt;a href=&quot;https://google.github.io/eng-practices/)#fridayreading&quot;&gt;https://google.github.io/eng-practices/)#fridayreading&lt;/a&gt; #codereview&lt;/p&gt;</content:encoded></item><item><title>Фраза недели - &quot;Результат не достижим, если едет только одно колесо&quot;</title><link>https://cherkashin.dev/posts/23/</link><guid isPermaLink="true">https://cherkashin.dev/posts/23/</guid><description>Фраза недели - &quot;Результат не достижим, если едет только одно колесо&quot;

Наткнулся на эту фразу в видео Бюро Горбунова, там и пример о работе есть, поэтому всем рекомендую посмотреть.

Немного от себя
Всегда приятно работать с людьми:

👉 которые не просто закрывают задачи, а смотрят немного шире;
👉 которые могут брать о...</description><pubDate>Wed, 13 Oct 2021 07:01:28 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Фраза недели&lt;/strong&gt; - “Результат не достижим, если едет только одно колесо”&lt;/p&gt;
&lt;p&gt;Наткнулся на эту фразу в &lt;a href=&quot;https://www.youtube.com/watch?v=1AJ_8InY8dk&amp;#x26;t=574s&quot;&gt;видео Бюро Горбунова&lt;/a&gt;, там и пример о работе есть, поэтому всем рекомендую посмотреть.&lt;/p&gt;
&lt;p&gt;**Немного от себя
**Всегда приятно работать с людьми:&lt;/p&gt;
&lt;p&gt;👉 которые не просто закрывают задачи, а смотрят немного шире;
👉 которые могут брать ответственность и помогать другим;
👉 мотивируют коллег просто тем, как они делают свою работу.&lt;/p&gt;
&lt;p&gt;Может показаться, что чтобы быть таким человеком, нужно перерабатывать и засиживаться допоздна, но это совершенно не так. Достаточно каждый день прикладывать совсем немного усилий, чтобы сделать продукт/компанию или чтобы то ни было лучше.&lt;/p&gt;
&lt;p&gt;Может показаться, что бизнесу лишь нужно, чтобы вы просто клепали свои задачи. Но коллеги и непосредственные руководители всё видят и знают, что на такого человека можно положиться, ведь он сделает всё в лучшем виде. А если не нужно, если не видят - то может стоит подыскать другую работу 😉.&lt;/p&gt;
&lt;p&gt;#weekphrase&lt;/p&gt;</content:encoded></item><item><title>Наткнулся на крутой доклад для тимлидов &quot;Теперь я - тимлид, но почему мне так плохо?&quot;, записал всё,…</title><link>https://cherkashin.dev/posts/22/</link><guid isPermaLink="true">https://cherkashin.dev/posts/22/</guid><description>Наткнулся на крутой доклад для тимлидов &quot;Теперь я - тимлид, но почему мне так плохо?&quot;, записал всё, что показалось важным. На самом деле он подходит любому, у кого больше обязанностей, чем просто писать код.

👉 Принцип Питера

👉 Не надо делать из хороших программистов плохих менеджеров. Не обязательно делать тимлида ...</description><pubDate>Sun, 03 Oct 2021 10:58:58 GMT</pubDate><content:encoded>&lt;p&gt;Наткнулся на крутой доклад для тимлидов “&lt;a href=&quot;https://www.youtube.com/watch?v=7fnY8WVtElY&quot;&gt;Теперь я - тимлид, но почему мне так плохо?&lt;/a&gt;”, записал всё, что показалось важным. На самом деле он подходит любому, у кого больше обязанностей, чем просто писать код.&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF_%D0%9F%D0%B8%D1%82%D0%B5%D1%80%D0%B0&quot;&gt;Принцип Питера&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;👉 Не надо делать из хороших программистов плохих менеджеров. Не обязательно делать тимлида из синьора, если у него нет нужных на то навыков. Может для него гораздо лучше будет стать техлидом.&lt;/p&gt;
&lt;p&gt;👉 Делегирование - ключ к успешной работе. Но нужно делегировать ответственность, а не задачи. Например, кто-то в команде может отвечать за код ревью, он ответственный за то, чтобы все пул/мерж реквесты получили фидбэк, были заапрувлены и были смержены.&lt;/p&gt;
&lt;p&gt;👉 Иногда технический бэкграунд только мешает, тимлиду может быть сложно доверять разработчикам, потому что он считает, что он сделал бы лучше. Чтобы было легче доверять команде, необходимо заниматься их ростом.&lt;/p&gt;
&lt;p&gt;👉 У тимлида должен быть асинхронный входящий канал связи. Так как через тимлида проходит всё информация, то естественно, что с вопросами все будут идти к нему. Если вас все время будут отвлекать, то вы просто не сможете нормально работать.&lt;/p&gt;
&lt;p&gt;👉 Заведите себе внешнее хранилище информации, где вы будете хранить все напоминания, задачи, чтобы можно было разгрузить свой мозг для более важных вещей. Например: Todoist, notion или Google Calendar.&lt;/p&gt;
&lt;p&gt;👉 Компетенции тимлида:
- Фокусировать
- Вдохновлять
- Коммуницировать
- Растить&lt;/p&gt;
&lt;p&gt;👉 Если ваша команда не растёт - вы плохой тимлид.&lt;/p&gt;
&lt;p&gt;👉 Необходимо узнавать у команды мнение о себе. С чем, по их мнению, вы справляетесь, а с чем нет. Какие у них претензии к вам.&lt;/p&gt;
&lt;p&gt;👉 Тимлид не болт пинает, если он не закрывает задачи самостоятельно, это не значит, что он ничего не делает. Чтобы команда это понимала, необходима прозрачность, необходимо рассказывать, что творится за пределами команды. Например, если на митингах вы обсуждаете, что-то, что коснётся и всю вашу команду, необходимо доносить эту информацию до команды.&lt;/p&gt;</content:encoded></item><item><title>Использование never в TypeScript</title><link>https://cherkashin.dev/posts/21/</link><guid isPermaLink="true">https://cherkashin.dev/posts/21/</guid><description>Использование never в TypeScript

Допустим мы хотим написать компонент диалог. Его размер может задаваться двумя различными способами:

Явно с помощью width и heightДиалог должен принять размер контента, за это отвечает свойство responsive

Интерфейс пропсов будет выглядеть как-то так.

interface DialogProps {
  // ......</description><pubDate>Wed, 29 Sep 2021 07:01:03 GMT</pubDate><content:encoded>&lt;p&gt;**Использование never в TypeScript&lt;/p&gt;
&lt;p&gt;**Допустим мы хотим написать компонент диалог. Его размер может задаваться двумя различными способами:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Явно с помощью &lt;code&gt;width&lt;/code&gt; и &lt;code&gt;height&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Диалог должен принять размер контента, за это отвечает свойство `responsive&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;`Интерфейс пропсов будет выглядеть как-то так.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;background-color:#22272e;color:#adbac7&quot; tabindex=&quot;0&quot; data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot;&gt;&lt;code data-language=&quot;tsx&quot; data-theme=&quot;github-dark-dimmed&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; DialogProps&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  // ... other properties&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;  height&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;  responsive&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt; Dialog&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;height&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;responsive&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; DialogProps&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;  // ...&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;```Тут есть несколько проблем:&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;1. Чтобы передать либо `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` и `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;height&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` или только `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;responsive&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` , мы пометили все поля как необязательные и теперь мы можем передать неправильный набор полей или не передать ни одного вовсе.&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;2. Можем передать все параметры одновременно и в таком случае непонятно, должен диалог быть отзывчивым или отобразиться с указанным размером. &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;Нам нужно реализовать тип, в котором все поля будут обязательными, но который позволит нам передать либо `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` и `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;height&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` либо `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;responsive&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` , в противном случае мы должны получить ошибку компиляции.&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;Такой интерфейс будет выглядеть вот так:&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;```&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;tsx&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; DialogProps&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  |&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;      responsive&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;      width&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; never&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;      height&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; never&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;  |&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;      responsive&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; never&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;      width&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F69D50&quot;&gt;      height&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;```**never** - пустое множество или проще говоря, это тип, которому не может быть присвоено ни одно значение.&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;```&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;tsx&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ✅ correct configuration&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; responsive&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; DialogProps&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  title: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Responsive Dialog&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  responsive: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ✅ correct &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; withSize&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; DialogProps&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  title: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Dialog with Size&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  width: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;600&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  height: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;500&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  responsive: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;undefined&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#768390&quot;&gt;// ❌ incorrect&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#F47067&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt; incorrect&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F69D50&quot;&gt; DialogProps&lt;/span&gt;&lt;span style=&quot;color:#F47067&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  title: &lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;&quot;Incorrect Props Dialog&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  responsive: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  width: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;600&lt;/span&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;  height: &lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;500&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#ADBAC7&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;```В третьем примере мы получим ошибку 🎉. На самом деле, мы могли бы использовать `&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` или `&lt;/span&gt;&lt;span style=&quot;color:#6CB6FF&quot;&gt;undefined&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` вместо `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;never&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` , но `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;never&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` выглядит более наглядно, потому что `&lt;/span&gt;&lt;span style=&quot;color:#DCBDFB&quot;&gt;never&lt;/span&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;` по своей сути показывает невозможные сценарии.&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;[Sandbox с примером.](https://codesandbox.io/s/either-or-types-qzxo0?file=/src/short-either-or.ts)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;**Ещё по теме&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;**- [Either/Or types in TypeScript](https://maecapozzi.com/either-or-types/)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;- [When to use &apos;never&apos; and &apos;unknown&apos; in TypeScript](https://blog.logrocket.com/when-to-use-never-and-unknown-in-typescript-5e4d6c5799ad/)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;color:#96D0FF&quot;&gt;- [TypeScript. Мощь never](https://habr.com/ru/post/471026/)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content:encoded></item><item><title>​​На прошлой неделе собрались с друзьями и обсудили персональный рост. Было много философских…</title><link>https://cherkashin.dev/posts/20/</link><guid isPermaLink="true">https://cherkashin.dev/posts/20/</guid><description>​​На прошлой неделе собрались с друзьями и обсудили персональный рост. Было много философских разговоров, вроде &quot;зачем всё это нужно - и так сойдёт&quot;, но всё же каждый смог вынести что-то для себя.

Зачем нужно изучать что-то новое?

Довольно сложный вопрос, на который не существует правильного ответа. Скорее всего кажд...</description><pubDate>Wed, 22 Sep 2021 07:00:44 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/332ad399b92e08f7d8fbe.jpg&quot;&gt;​​&lt;/a&gt;На прошлой неделе собрались с друзьями и обсудили персональный рост. Было много философских разговоров, вроде “зачем всё это нужно - и так сойдёт”, но всё же каждый смог вынести что-то для себя.&lt;/p&gt;
&lt;p&gt;**Зачем нужно изучать что-то новое?&lt;/p&gt;
&lt;p&gt;**Довольно сложный вопрос, на который не существует правильного ответа. Скорее всего каждый объяснит это по-своему, а возможно кто-то и вовсе не сможет объяснить. Я бы выделил следующие причины:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Просто интересно и ты от этого кайфуешь;&lt;/li&gt;
&lt;li&gt;Повысить свою квалификацию, должность и соответственно зарплату;&lt;/li&gt;
&lt;li&gt;Быть готовым к смене работы, ведь возможно твои навыки уже не очень актуальны для других работодателей;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Возможно после достижения какого-то уровня, действительно нет смысла развиваться в определенном направлении. Если у вас хороший уровень английского, возможно будет полезнее изучить алгоритмы или архитектуру, чем вкладывать усилия в язык.&lt;/p&gt;
&lt;p&gt;**Как изучать что-то новое?&lt;/p&gt;
&lt;p&gt;Что изучать&lt;/p&gt;
&lt;p&gt;**Для начала нужно разобраться, что именно необходимо изучать. Возможно вы уже знаете ответ на этот вопрос. И это нормально “не знать, чем ты хочешь заниматься”. Чтобы понять - необходимо пробовать, только так можно осознать, что именно тебе интересно. А чтобы понять, что попробовать можно воспользоваться вот этими советами:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Изучать то, что по-настоящему вас увлекает и приносит вам удовольствие;&lt;/li&gt;
&lt;li&gt;Понять на что вы тратите больше всего времени. Если вы тратите час на написание имейла на английском - возможно пора уделить время английскому;&lt;/li&gt;
&lt;li&gt;Выписать проблемы, с которыми вы сталкиваетесь в текущем проекте и понять, что вы можете изучить, чтобы решать их быстрее. Это может быть что угодно: множество регрессий, отсутствие процессов в команде, а может вы просто тратите кучу времени на Code Review;&lt;/li&gt;
&lt;li&gt;Поговорить с друзьями и узнать, чем они занимаются на работе, какие проблемы решают, какие технологии/инструменты используют;&lt;/li&gt;
&lt;li&gt;Походить по собеседованиям и узнать, на что есть спрос в других компаниях.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;При этом необходимо понимать, чего именно в итоге вы хотите добиться. Должна быть возможность оценить ваш прогресс, иначе мотивация быстро сойдёт на нет.&lt;/p&gt;
&lt;p&gt;**Как изучать&lt;/p&gt;
&lt;p&gt;**После того, как стало ясно в каком направлении двигаться, необходим план достижения цели. План состоит из нескольких частей:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Путь достижения цели: материалы, которые необходимо изучить; проекты, которые необходимо выполнить;&lt;/li&gt;
&lt;li&gt;То как вы будете идти по этому пути. Будете ли вы идти самостоятельно или с проводником (ментором), который поможет быстрее дойти до конечно точки и не заблудиться.&lt;/li&gt;
&lt;li&gt;Очень важно выработать привычку, необходимо превратить обучение в рутину. Например, можно уделять ежедневно час утром.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**Смена работы&lt;/p&gt;
&lt;p&gt;**Можно засидеться на одной работе и почувствовать стагнацию в своём развитии:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вы используете одни и те же инструменты;&lt;/li&gt;
&lt;li&gt;тратите больше времени на изучение легаси кода и баг фиксы, чем на саморазвитие.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Смена работы, в какой-то степени может решить эту проблему. Скорее всего в начале вы начнёте невероятно быстро расти, пока будете изучать новый проект и технологии, которые там используются.&lt;/p&gt;
&lt;p&gt;Но есть вероятность вернуться на исходную точку, когда вы изучили все технологии и глубже погрузились в проект:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вы вновь используете одни и те же инструменты;&lt;/li&gt;
&lt;li&gt;задачи однообразные и больше не кажутся такими интересными;&lt;/li&gt;
&lt;li&gt;снова всё обросло сплошным легаси;&lt;/li&gt;
&lt;li&gt;вы снова думаете о смене работы, ведь вы снова перестали развиваться.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Лучше не отдавать на откуп своё развитие внешним факторам, вроде смены работы. Правильнее самому заняться своим развитием.&lt;/p&gt;
&lt;p&gt;**Вместо концовки&lt;/p&gt;
&lt;p&gt;**Это то, что я смог вынесли из нашего разговора. А ещё можете &lt;a href=&quot;https://vk.com/away.php?to=https%3A%2F%2Fabtv.github.io%2Fnotes%2FLearning&amp;#x26;cc_key=&quot;&gt;почитать заметки друга&lt;/a&gt;, который участвовал в обсуждении.&lt;/p&gt;</content:encoded></item><item><title>​​Как избавиться от прерываний</title><link>https://cherkashin.dev/posts/19/</link><guid isPermaLink="true">https://cherkashin.dev/posts/19/</guid><description>​​Как избавиться от прерываний

Сегодня я хочу вам рассказать о самой большой причине моей раздражительности и усталости - прерываниях и многозадачности.

Проблему легко описать на примере следующей ситуации.

Обычный рабочий день:

вы заняты решением какой-то проблемы - вы полностью сосредоточенываш коллега задаёт вам...</description><pubDate>Wed, 15 Sep 2021 06:14:35 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/73f2a8bb51f778115259c.jpg&quot;&gt;​​&lt;/a&gt;**Как избавиться от прерываний&lt;/p&gt;
&lt;p&gt;**Сегодня я хочу вам рассказать о самой большой причине моей раздражительности и усталости - прерываниях и многозадачности.&lt;/p&gt;
&lt;p&gt;Проблему легко описать на примере следующей ситуации.&lt;/p&gt;
&lt;p&gt;Обычный рабочий день:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вы заняты решением какой-то проблемы - вы полностью сосредоточены&lt;/li&gt;
&lt;li&gt;ваш коллега задаёт вам какой-то вопрос&lt;/li&gt;
&lt;li&gt;вы стараетесь продолжать работать и ответить коллеге (💡 многозадачность)&lt;/li&gt;
&lt;li&gt;вы вынуждены прерваться и переспросить вопрос ⏳&lt;/li&gt;
&lt;li&gt;вникаете в вопрос, чтобы ответить на него&lt;/li&gt;
&lt;li&gt;отвечаете на вопрос&lt;/li&gt;
&lt;li&gt;возвращаетесь к работе и пытаетесь вспомнить на чём же вы остановились ⏳.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Мозг не способен эффективно делать две вещи одновременно, поэтому, в данной ситуации, мы тратим кучу времени, чтобы переключиться с решения своей задачи, а потом вернуться к ней. С помощью ⏳, я отметил где мы тратим время и “мыслетопливо”.&lt;/p&gt;
&lt;p&gt;Ситуации, когда мы вынуждены прервать работу из-за коллеги, телефонного звонка или чего угодно ещё называются &lt;strong&gt;пассивными прерываниями&lt;/strong&gt;. Мы не можем полностью от них избавиться, но мы можем свести их к минимуму. Есть пара простых советов:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Митинги&lt;/strong&gt;. Запланируйте встречи с людьми, с которыми вы чаще всего коммуницируете. Записывайте все накопившиеся вопросы (попросите о том же остальных) и обсудите всё за раз. Чем чаще вы взаимодействуете с человеком, тем чаще нужно проводить встречи. Например: ежедневные стендапы с командой, еженедельные митинги с дизайнером.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Почта вместо мессенджеров&lt;/strong&gt;. Корпоративные чаты зачастую убивают нашу продуктивность, сам формат чатов предполагает, что вы должны сразу ответить на сообщение, что ничем не отличается от ситуации описанной выше. Если вопрос не требует немедленного внимания, попросите ваших коллег отправлять email’ы, чтобы вы могли на них ответить в удобное для вас время.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Напоследок приведу цитату Дэвида Аллена:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Нежелательно, чтобы вы и человек, которому вы хотите делегировать свой вопрос, прерывались и оставляли текущие дела, чтобы обсудить вашу задачу. Это будет быстро, но нарушит и ваш, и его рабочий процесс. К тому же у этого варианта такой же недостаток, как и у голосовой почты: разговор не фиксируется письменно.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ещё по теме:
&lt;a href=&quot;https://www.litres.ru/deyv-krenshou/mif-o-mnogozadachnosti-k-chemu-privodit-stremlenie-uspet-vse/&quot;&gt;Миф о многозадачности. К чему приводит стремление всё успеть.&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Самый простой способ хостинга ваших пэт проектов</title><link>https://cherkashin.dev/posts/17/</link><guid isPermaLink="true">https://cherkashin.dev/posts/17/</guid><description>Самый простой способ хостинга ваших пэт проектов

 Нужно сделать всего 5 простых шагов:

Устанавливаете пакет gh-pages следующим образом yarn add --dev gh-pages

2. Добавляете скрипты в package.json

&quot;predeploy&quot;: &quot;yarn run build&quot;,
&quot;deploy&quot;: &quot;gh-pages -d build&quot;

3. Добавляете homepage в package.json в следующем формате
...</description><pubDate>Thu, 09 Sep 2021 06:32:02 GMT</pubDate><content:encoded>&lt;p&gt;**Самый простой способ хостинга ваших пэт проектов&lt;/p&gt;
&lt;p&gt;** Нужно сделать всего 5 простых шагов:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Устанавливаете пакет &lt;code&gt;gh-pages&lt;/code&gt; следующим образом `yarn add —dev gh-pages&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;2. Добавляете скрипты в &lt;/code&gt;package.json&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;predeploy&quot;: &quot;yarn run build&quot;,
&quot;deploy&quot;: &quot;gh-pages -d build&quot;

```3. Добавляете `homepage` в package.json в следующем формате

`http://&amp;#x3C;github-username&gt;.github.io/&amp;#x3C;project-name&gt;

`4. Деплоите `yarn deploy

`5. Меняете ветку в настройках github pages на gh-pages и не забудьте нажать кнопочку Save 

Открываете свой сайт по адресу `http://&amp;#x3C;github-username&gt;.github.io/&amp;#x3C;project-name&gt;` - например &amp;#x3C;https://acherkashin.github.io/yandex-music-open-api/&gt; и хвастаетесь своим друзьям.

Подробнее можно [почитать здесь](https://medium.com/mobile-web-dev/how-to-build-and-deploy-a-react-app-to-github-pages-in-less-than-5-minutes-d6c4ffd30f14) и в [официальной документации](https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages).
&lt;/code&gt;&lt;/pre&gt;</content:encoded></item><item><title>​​Небольшой отчёт за прошедший отпуск</title><link>https://cherkashin.dev/posts/16/</link><guid isPermaLink="true">https://cherkashin.dev/posts/16/</guid><description>​​Небольшой отчёт за прошедший отпуск

✅ 2 недели без ноута

✅ Убедился, что на Дериглазова не такие уж и большие пробки по сравнению с Сочи

✅ Прочитал пару книг. Особенно приятно. Обычно не удаётся найти времени на чтение.

Загадочная история Билли МиллиганаЦветы для Элджернона

✅ Отдохнул и снова захотел работать.

...</description><pubDate>Sun, 22 Aug 2021 11:48:01 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/66a23428d1f49640b185b.jpg&quot;&gt;​​&lt;/a&gt;**Небольшой отчёт за прошедший отпуск&lt;/p&gt;
&lt;p&gt;**✅ 2 недели без ноута&lt;/p&gt;
&lt;p&gt;✅ Убедился, что на Дериглазова не такие уж и большие пробки по сравнению с Сочи&lt;/p&gt;
&lt;p&gt;✅ Прочитал пару книг. Особенно приятно. Обычно не удаётся найти времени на чтение.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Загадочная история Билли Миллигана&lt;/li&gt;
&lt;li&gt;Цветы для Элджернона&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✅ Отдохнул и снова захотел работать.&lt;/p&gt;
&lt;p&gt;❌ Не смотреть политические видео.&lt;/p&gt;
&lt;p&gt;В последние дни постоянно лил дождь, стало скучно и сорвался.&lt;/p&gt;
&lt;p&gt;❌ Не читать рабочие переписки.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Открыв рабочий чат в первый раз, увидел, что мы вероятно что-то сломали некоторое время назад.&lt;/li&gt;
&lt;li&gt;Во второй раз - Коллега уволился.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Рабочие чаты это отдельная тема. Никак не могу перестать читать их во вне рабочее время, на выходных и во время отпуска. Это нездоровая штука, которая лишь заставляет нервничать и не приносит никакой пользы. В своё оправдание могу сказать, что сорвался лишь пару раз.&lt;/p&gt;
&lt;p&gt;Не будьте как я - не читайте рабочие чаты.&lt;/p&gt;</content:encoded></item><item><title>​​Accessibility Course</title><link>https://cherkashin.dev/posts/15/</link><guid isPermaLink="true">https://cherkashin.dev/posts/15/</guid><description>​​Accessibility Course

В прошлом году услышал о курсе про Accessibility, и появилось желание рассеять &quot;туман войны&quot; вокруг данной тематики. Спустя полтора месяца лекций, есть полное понимание, как и главное для чего делать интерфейсы доступными.

Если в двух словах, интерфейсы являются доступными, если ими могут польз...</description><pubDate>Sat, 03 Jul 2021 08:00:38 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/6b4a9c176ffdf8be34239.jpg&quot;&gt;​​&lt;/a&gt;**Accessibility Course&lt;/p&gt;
&lt;p&gt;**В прошлом году услышал о курсе про Accessibility, и появилось желание рассеять “туман войны” вокруг данной тематики. Спустя полтора месяца лекций, есть полное понимание, как и главное для чего делать интерфейсы доступными.&lt;/p&gt;
&lt;p&gt;Если в двух словах, интерфейсы являются доступными, если ими могут пользоваться люди с ограниченными возможностями. Например, слабовидящие с использованием скринзума, слепые с помощью скринридера.&lt;/p&gt;
&lt;p&gt;Все преподаватели невероятно любят то, чем занимаются и читают лекции с удовольствием, зная о чём говорят. Было невероятно круто. Теперь нужно ещё разок пересмотреть лекции и нарабатывать практику.&lt;/p&gt;
&lt;p&gt;PS: Даже &lt;a href=&quot;https://kurmak.info/certificate/AlexanderCherkashin&quot;&gt;сертификат&lt;/a&gt; свёрстан доступно 😉&lt;/p&gt;</content:encoded></item><item><title>​​Проапгрейдил рабочее место 👨‍💻</title><link>https://cherkashin.dev/posts/14/</link><guid isPermaLink="true">https://cherkashin.dev/posts/14/</guid><description>​​Проапгрейдил рабочее место 👨‍💻</description><pubDate>Sun, 06 Jun 2021 18:59:21 GMT</pubDate><content:encoded>&lt;p&gt;​​&lt;a href=&quot;https://telegra.ph/file/7e7817551a90bfc475072.jpg&quot;&gt;Проапгрейдил&lt;/a&gt; рабочее место 👨‍💻&lt;/p&gt;</content:encoded></item><item><title>Yandex Music OpenAPI</title><link>https://cherkashin.dev/posts/13/</link><guid isPermaLink="true">https://cherkashin.dev/posts/13/</guid><description>Yandex Music OpenAPI

Уже некоторое время пилю OpenAPI схему для Яндекс Музыки. Сейчас существует только одна полноценная библиотека для взаимодействия с сервисом, написанная на питоне, поэтому я решил что было бы неплохо написать схему, с помощью которой можно будет генерировать библиотеку для каждого языка. Как обычн...</description><pubDate>Sat, 05 Jun 2021 18:32:48 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/acherkashin/yandex-music-open-api&quot;&gt;Yandex Music OpenAPI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Уже некоторое время пилю OpenAPI схему для Яндекс Музыки. Сейчас существует только одна полноценная библиотека для взаимодействия с сервисом,&lt;a href=&quot;https://github.com/MarshalX/yandex-music-api&quot;&gt; написанная на питоне&lt;/a&gt;, поэтому я решил что было бы неплохо написать схему, с помощью которой можно будет генерировать библиотеку для каждого языка. Как обычно любой фидбек, пулреквесты и звёздочки на гитхабе категорически приветствуются.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/acherkashin/yandex-music-open-api&quot;&gt;https://github.com/acherkashin/yandex-music-open-api&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Ресурсы для успешного прохождения собеседования</title><link>https://cherkashin.dev/posts/12/</link><guid isPermaLink="true">https://cherkashin.dev/posts/12/</guid><description>Ресурсы для успешного прохождения собеседования

Прежде чем проходить собеседование, не плохо было бы подготовиться:
1) Освежи в памяти свои технические знания.
2) Чтобы не быть застигнутым врасплох, узнай базовый список вопросов, которые задают при прохождении собеседования. Например, &quot;Почему вы решили сменить текущее...</description><pubDate>Sun, 25 Apr 2021 19:42:03 GMT</pubDate><content:encoded>&lt;p&gt;**Ресурсы для успешного прохождения собеседования&lt;/p&gt;
&lt;p&gt;**Прежде чем проходить собеседование, не плохо было бы подготовиться:
1) Освежи в памяти свои технические знания.
2) Чтобы не быть застигнутым врасплох, узнай базовый список вопросов, которые задают при прохождении собеседования. Например, “Почему вы решили сменить текущее место работы?”, “Что вас не устраивает на текущем месте работы?” или “Какие ваши зарплатные ожидания?“.
3) Подготовь список вопросов для работодателя, чтобы не терять время во время интервью.&lt;/p&gt;
&lt;p&gt;Вам нет необходимости проводить много времени в интернете собирая необходимую для собеседования информацию, для этого есть готовые ресурсы. Вот лишь некоторые из них:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://h5bp.org/Front-end-Developer-Interview-Questions/&quot;&gt;FrontEnd developer interview questions
&lt;/a&gt;&lt;a href=&quot;https://www.techinterviewhandbook.org/&quot;&gt;FrontEnd interview handbook&lt;/a&gt; - ответы на &lt;a href=&quot;https://h5bp.org/Front-end-Developer-Interview-Questions/&quot;&gt;FrontEnd developer interview questions
&lt;/a&gt;&lt;a href=&quot;https://yangshun.github.io/tech-interview-handbook/&quot;&gt;Tech Interview Handbook
&lt;/a&gt;&lt;a href=&quot;https://github.com/viraptor/reverse-interview&quot;&gt;Reverse interview&lt;/a&gt; - вопросы кандидата к работодателю
&lt;a href=&quot;https://itvdn.com/ru/blog/article/150-questions-net-developer&quot;&gt;150+ Вопросов по .Net для junior, middle и senior&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>​​Code Review</title><link>https://cherkashin.dev/posts/11/</link><guid isPermaLink="true">https://cherkashin.dev/posts/11/</guid><description>​​Code Review

Обычно говоря о код ревью, мы подразумеваем процесс, когда код отправляется от автора фичи к другому разработчику для проверки его правильности. Однако помимо этого, код ревью выполняет ещё одну важную функцию - распространение знаний о коде. Если у вас в команде код проходит стадию Code Review, то по кр...</description><pubDate>Sat, 20 Mar 2021 17:00:46 GMT</pubDate><content:encoded>&lt;p&gt;​​&lt;a href=&quot;https://telegra.ph/file/d543d1b4d7082b6dd440f.jpg&quot;&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/a&gt;** Review**&lt;/p&gt;
&lt;p&gt;Обычно говоря о код ревью, мы подразумеваем процесс, когда код отправляется от автора фичи к другому разработчику для проверки его правильности. Однако помимо этого, код ревью выполняет ещё одну важную функцию - распространение знаний о коде. Если у вас в команде код проходит стадию Code Review, то по крайней мере несколько человек знают о внесённых изменениях.&lt;/p&gt;
&lt;p&gt;Код ревью - определенно хорошая практика, которая может предотвратить попадание ошибок в прод и улучшить кодовую базу. Но в то же время плохо настроенный процесс код ревью может значительно замедлить разработку. Ваш Pull Request, может ожидать несколько дней, а то и недель, пока ваш коллега найдёт время, чтобы взглянуть на него. Через неделю, ваш дружелюбный коллега оставит несколько комментариев, после чего вам потребуется ещё пара дней на исправления. Но в то же время, ваш менеджер сообщит вам, что релиз придётся перенести, потому что ваша задача не выполнена?!?!?!&lt;/p&gt;
&lt;p&gt;И это ещё не всё! Бывают случаи, когда код ревью является сильнейшим демотиватором. Это особенно заметно, когда ревьюер, придираясь к каждой строчке, показывает своё превосходство, после чего ваши отношения начинают портиться, и вы старательно его избегаете.&lt;/p&gt;
&lt;p&gt;Поэтому очень важно не только проводить код ревью, но и проводить его правильно.&lt;/p&gt;
&lt;p&gt;Как правильно проводить код ревью:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://google.github.io/eng-practices/review/reviewer/&quot;&gt;Google’s Engineering Practices documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;“&lt;a href=&quot;https://github.com/CSSSR/sputnik/issues/79&quot;&gt;Уточнения о процессе Code Review” - Issue в репозитории CSSSR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ещё по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sputnik.csssr.ru/Git/PullRequests.html&quot;&gt;Создание и сопровождение Pull Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sharovatov.github.io/entries/2020-12-coderevie&quot;&gt;Code review — долго, плохо, дорого&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Небольшой совет для ревьюеров - Код ревью лучше делать, когда ты не находишься в контексте другой задачи, так как переключение контекста является довольно время и энерго затратной операцией. Иными словами лучше делать код ревью:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;после завершения задачи&lt;/li&gt;
&lt;li&gt;утром&lt;/li&gt;
&lt;li&gt;после обеда&lt;/li&gt;
&lt;li&gt;после завершения дейли-митинга.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>​​Отладка фокуса в браузере</title><link>https://cherkashin.dev/posts/10/</link><guid isPermaLink="true">https://cherkashin.dev/posts/10/</guid><description>​​Отладка фокуса в браузере

В последние несколько месяцев у меня было несколько задач связанных с отладкой фокуса, в одних случаях он пропадал неизвестно куда, в других появлялся неизвестно откуда.

Получить текущий активный элемент, или проще говоря — элемент в фокусе, достаточно просто — document.activeElement. С по...</description><pubDate>Tue, 09 Mar 2021 18:00:47 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/fd7b96949d5f573e8410d.mp4&quot;&gt;​​&lt;/a&gt;**Отладка фокуса в браузере&lt;/p&gt;
&lt;p&gt;**В последние несколько месяцев у меня было несколько задач связанных с отладкой фокуса, в одних случаях он пропадал неизвестно куда, в других появлялся неизвестно откуда.&lt;/p&gt;
&lt;p&gt;Получить текущий активный элемент, или проще говоря — элемент в фокусе, достаточно просто — &lt;em&gt;&lt;strong&gt;document.activeElement&lt;/strong&gt;&lt;/em&gt;. С помощью следующей нехитрой конструкции мы сможем логировать элемент, который получает фокус:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;document.addEventListener(&apos;focusin&apos;,  () =&gt; {   console.log(&apos;focused: &apos;, document.activeElement); }, true);&lt;/code&gt;*&lt;/p&gt;
&lt;p&gt;*Другим способом является использование фичи Developer Tools - Live Expressions.&lt;/p&gt;
&lt;p&gt;Мне больше нравится первый вариант, так как в консоли остаётся вся цепочка элементов, которые были в фокусе.&lt;/p&gt;
&lt;p&gt;**Ещё по теме:
**&lt;a href=&quot;https://vk.com/away.php?to=https%3A%2F%2Fhiddedevries.nl%2Fen%2Fblog%2F2019-01-30-console-logging-the-focused-element-as-it-changes&amp;#x26;cc_key=&quot;&gt;1. Console logging the focused element as it changes
&lt;/a&gt;&lt;a href=&quot;https://vk.com/away.php?to=https%3A%2F%2Fdevelopers.google.com%2Fweb%2Ftools%2Fchrome-devtools%2Faccessibility%2Ffocus&amp;#x26;cc_key=&quot;&gt;2. Track Which Element Has Focus
&lt;/a&gt;&lt;a href=&quot;https://vk.com/away.php?to=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FCSS%2F%3Afocus&amp;#x26;cc_key=&quot;&gt;3. Псевдо-класс :focus&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>​​Наконец-то дошли руки завести LinkedIn.</title><link>https://cherkashin.dev/posts/9/</link><guid isPermaLink="true">https://cherkashin.dev/posts/9/</guid><description>​​Наконец-то дошли руки завести LinkedIn.

Установите расширение &quot;Доступ к LinkedIn&quot; для Chrome и забудьте, что он заблокирован в России 😉.</description><pubDate>Sat, 27 Feb 2021 09:24:28 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/fc208aa7b28dbef067a2d.jpg&quot;&gt;​​&lt;/a&gt;Наконец-то дошли руки завести LinkedIn.&lt;/p&gt;
&lt;p&gt;Установите расширение &lt;a href=&quot;https://chrome.google.com/webstore/detail/%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF-%D0%BA-linkedin/cgfhdokcgndnhkcjapbfanddfhecklio?hl=ru&quot;&gt;“Доступ к LinkedIn&lt;/a&gt;” для Chrome и забудьте, что он заблокирован в России 😉.&lt;/p&gt;</content:encoded></item><item><title>​​C# Interactive - REPL</title><link>https://cherkashin.dev/posts/8/</link><guid isPermaLink="true">https://cherkashin.dev/posts/8/</guid><description>​​C# Interactive - REPL

REPL или “read-eval-print loop” - это интерактивная среда разработки (в командной строке), в которой пользователь вводит выражение на языке программирования, а REPL, в свою очередь, считывает Read его, выполняет Eval и отображает результат Print, а затем этот процесс снова повторяется Loop.</description><pubDate>Sat, 27 Feb 2021 09:10:07 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/946436d80d91d5b3621fe.jpg&quot;&gt;​​&lt;/a&gt;**C# Interactive - REPL&lt;/p&gt;
&lt;p&gt;**REPL или “read-eval-print loop” - это интерактивная среда разработки (в командной строке), в которой пользователь вводит выражение на языке программирования, а REPL, в свою очередь, считывает &lt;strong&gt;Read&lt;/strong&gt; его, выполняет &lt;strong&gt;Eval&lt;/strong&gt; и отображает результат &lt;strong&gt;Print&lt;/strong&gt;, а затем этот процесс снова повторяется &lt;strong&gt;Loop&lt;/strong&gt;.&lt;/p&gt;</content:encoded></item><item><title>​​Visual Studio Code ❤️ Яндекс.Музыка</title><link>https://cherkashin.dev/posts/6/</link><guid isPermaLink="true">https://cherkashin.dev/posts/6/</guid><description>​​Visual Studio Code ❤️ Яндекс.Музыка

Последние несколько месяцев разрабатываю расширение Яндекс.Музыки для Visual Studio Code. Сейчас оно находится в достаточно стабильном состоянии (не без багов, конечно).

Если вы устали постоянно держать открытой вкладку с Яндекс.Музыкой, то вам просто необходимо его попробовать. ...</description><pubDate>Sat, 27 Feb 2021 08:51:41 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://telegra.ph/file/9e55ebc5086fa75b42002.jpg&quot;&gt;​​&lt;/a&gt;**Visual Studio Code ❤️ Яндекс.Музыка&lt;/p&gt;
&lt;p&gt;**Последние несколько месяцев разрабатываю расширение Яндекс.Музыки для Visual Studio Code. Сейчас оно находится в достаточно стабильном состоянии (не без багов, конечно).&lt;/p&gt;
&lt;p&gt;Если вы устали постоянно держать открытой вкладку с Яндекс.Музыкой, то вам просто необходимо его попробовать. Или можете просто поддержать звездочкой на GitHub. Критика, рекомендации по улучшению и Issue на GitHub категорически приветствуются.&lt;/p&gt;
&lt;p&gt;#vscode #yandexmusic #extension&lt;/p&gt;</content:encoded></item><item><title>Навигация с клавиатуры</title><link>https://cherkashin.dev/posts/4/</link><guid isPermaLink="true">https://cherkashin.dev/posts/4/</guid><description>[Навигация с клавиатуры

](https://www.cherkashin.dev/accessibility/html/css/2020/06/05/keyboard-navigation.html)В большинстве статей по Accessibility вы прочтете, что доступность помогает людям с ограниченными возможностями. Но зачастую, мы не задумываемся об этом совсем или задумываемся в последнюю очередь (сроки то ...</description><pubDate>Sat, 27 Feb 2021 08:31:07 GMT</pubDate><content:encoded>&lt;p&gt;[Навигация с клавиатуры&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://www.cherkashin.dev/accessibility/html/css/2020/06/05/keyboard-navigation.html)%D0%92&quot;&gt;https://www.cherkashin.dev/accessibility/html/css/2020/06/05/keyboard-navigation.html)В&lt;/a&gt; большинстве статей по Accessibility вы прочтете, что доступность помогает людям с ограниченными возможностями. Но зачастую, мы не задумываемся об этом совсем или задумываемся в последнюю очередь (сроки то горят), лишая многих людей возможности пользоваться нашим приложением. Но сегодня я хочу поговорить именно о нас с вами, и о том, как мы можем упростить свою жизнь. Как вы уже поняли из названия, речь пойдет не об Accessibility в целом, а только об одном её аспекте - навигации с клавиатуры.&lt;/p&gt;
&lt;p&gt;#keyboard  #keyboardnavigation #accessibility&lt;/p&gt;</content:encoded></item><item><title>Пишем Visual Studio Code extension для VirtualBox</title><link>https://cherkashin.dev/posts/3/</link><guid isPermaLink="true">https://cherkashin.dev/posts/3/</guid><description>[Пишем Visual Studio Code extension для VirtualBox

](https://www.cherkashin.dev/vscode/typescript/extension/2020/04/14/virtualbox-vscode-extension.html)VS Code достаточно мощный текстовый редактор, куда с помощью различных расширений интегрирована куча всевозможных инструментов. Мне всегда невероятно больно, когда нуж...</description><pubDate>Sat, 27 Feb 2021 08:23:06 GMT</pubDate><content:encoded>&lt;p&gt;[Пишем Visual Studio Code extension для VirtualBox&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://www.cherkashin.dev/vscode/typescript/extension/2020/04/14/virtualbox-vscode-extension.html)VS&quot;&gt;https://www.cherkashin.dev/vscode/typescript/extension/2020/04/14/virtualbox-vscode-extension.html)VS&lt;/a&gt; Code достаточно мощный текстовый редактор, куда с помощью различных расширений интегрирована куча всевозможных инструментов. Мне всегда невероятно больно, когда нужно покидать его, потому что я сразу начинаю путаться в окнах и забываю, что я вообще хотел сделать. Я думаю, каждый хоть раз терялся во всех открытых им окнах, поэтому предположу, что вам это знакомо. У меня установлено несколько виртуальных машин, и меня невероятно раздражает, что для их запуска нужно открыть VirtualBox просто чтобы нажать кнопку Run. Собственно говоря, сегодня я расскажу, как избавился от своей боли.&lt;/p&gt;
&lt;p&gt;Это статья проведет вас через весь путь создания VirtualBox extension - от генерации базового шаблона, до управления виртуалками из VS Code.&lt;/p&gt;</content:encoded></item><item><title>C# Interactive - REPL</title><link>https://cherkashin.dev/articles/csharp-repl/</link><guid isPermaLink="true">https://cherkashin.dev/articles/csharp-repl/</guid><description>Несколько лет назад, я заметил, что в Visual Studio появилась новая окошко &quot;C# Interactive&quot;. Eщё тогда я стал догадываться, что это REPL, однако только недавно решил разобраться, что оно из себя представляет и в каких случаях может быть полезно. Прежде чем мы перейдём, к &quot;С# Interactive&quot; давайте кратко обсудим, что же такое REPL.</description><pubDate>Sat, 26 Sep 2020 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/csharp-repl/repl-meme.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/csharp-repl/repl-meme.png"/></item><item><title>Навигация с клавиатуры</title><link>https://cherkashin.dev/articles/keyboard-navigation/</link><guid isPermaLink="true">https://cherkashin.dev/articles/keyboard-navigation/</guid><description>В большинстве статей по Accessibility вы прочтете, что доступность помогает людям с ограниченными возможностями. Но зачастую, мы не задумываемся об этом совсем или задумываемся в последнюю очередь (сроки то горят), лишая многих людей возможности пользоваться нашим приложением. Но сегодня я хочу поговорить именно о нас с вами, и о том, как мы можем упростить свою жизнь.</description><pubDate>Fri, 05 Jun 2020 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/keyboard-navigation/yandex-keyboard-order.gif" medium="image"/><media:thumbnail url="https://cherkashin.dev/keyboard-navigation/yandex-keyboard-order.gif"/></item><item><title>Пишем Visual Studio Code extension для VirtualBox</title><link>https://cherkashin.dev/articles/virtualbox-vscode-extension/</link><guid isPermaLink="true">https://cherkashin.dev/articles/virtualbox-vscode-extension/</guid><description>VS Code достаточно мощный текстовый редактор, куда с помощью различных расширений интегрирована куча всевозможных инструментов. Мне всегда невероятно больно, когда нужно покидать его, потому что я сразу начинаю путаться в окнах и забываю, что я вообще хотел сделать. Я думаю, каждый хоть раз терялся ~~в трех соснах~~ во всех открытых им окнах, поэтому предположу, что вам это знакомо. У меня установлено несколько виртуальных машин, и меня невероятно раздражает, что для их запуска нужно открыть VirtualBox просто чтобы нажать кнопку **Run**. Собственно говоря, сегодня я расскажу, как избавился от своей боли.</description><pubDate>Tue, 14 Apr 2020 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/virtualbox-vscode-extension/vms-list.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/virtualbox-vscode-extension/vms-list.png"/></item><item><title>Сравнение C# и JavaScript. Основы</title><link>https://cherkashin.dev/articles/csharp-js-comparison/</link><guid isPermaLink="true">https://cherkashin.dev/articles/csharp-js-comparison/</guid><description>В данной статье я бы хотел систематизировать свои базовые знания об этих языках и рассмотреть их сходства и различия. Данная статья может служить руководством для C# разработчиков, которые хотят изучить JavaScript и наоборот. Также хочу заметить, что в данной статье описываются возможности клиентского JS, так как опыта разработки на Node.js у меня нет. Итак, если вы все ещё не потеряли интерес — приступим.</description><pubDate>Tue, 19 Jun 2018 00:00:00 GMT</pubDate><media:content url="https://cherkashin.dev/csharp-js-comparison/article-logo.png" medium="image"/><media:thumbnail url="https://cherkashin.dev/csharp-js-comparison/article-logo.png"/></item></channel></rss>