TGViewer
Channel Public Channel
isqualog • front-end • productivity

isqualog • front-end • productivity

@isqualog

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

Лонгриды тут → https://isqua.ru/
Subscribers
586
Photos
30
Videos
5
Links
71
Recent Posts 16 shown
Post #126 271
Диктовка

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

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

И то ли у меня с дикцией чё-то не то, то ли я натолкнулся на парадигму «сначала ориентируем продукт в США, а потом может быть когда-нибудь и на остальной мир». Потому что для меня диктовка работает откровенно плохо.

На компе общаюсь с коллегами — диктую на английском. Но произношение моё недостаточно american, и 1-2 words в каждой sentence распознаётся неправильно, you know. В итоге это занимает больше времени чем печать — а печатаю я быстро.

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

Когда уже нормальное будущее с нормальными языковыми технологиями наступит?
  • 😁 11
  • 👍 1
Post #125 380
Видели уже страничку с пулреквестами в гитхабе? Я только сегодня обнаружил редизайн, обычно как-то захожу в конкретную репу свои PR смотреть. Удобно в целом!

https://github.com/pulls/inbox
Post #124 588
isqualog • front-end • productivity Европу накрыла heat wave, поэтому сегодня у нас рубрика РАСПАКОВКА В Германии кондиционеры делают, но не устанавливают. Как охлаждаться? Сгонял в аптеку и магаз, купил: 1. Охлаждающий гелевый пакет (справа снизу). В морозилку его, он замерзает, потом кладёте…
пожалуйста уберите огонёчек, и так жарко
  • 😁 17
  • 🔥 13
Post #122 586
Европу накрыла heat wave, поэтому сегодня у нас рубрика РАСПАКОВКА

В Германии кондиционеры делают, но не устанавливают. Как охлаждаться? Сгонял в аптеку и магаз, купил:

1. Охлаждающий гелевый пакет (справа снизу). В морозилку его, он замерзает, потом кладёте на голову или куда вам там надо

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

3. Изотоник в таблетках. С потом теряем электролиты, с водой их не восполняем. Работает как терафлю — кидаете таблетку в воду, она шипит и растворяется, пьёте.

4. Протеиновое мороженое (ведёрко). Совмещаем приятное с полезным.

5. Физраствор, он же NaCl 0,9% (ампулки по центру). Это не от жары, я всегда ношу с собой и пополнил запасы. Мало ли что в глаз попадёт — промыть, да и в целом в экран смотрю, глаза сохнут — капаю иногда. Или ранку промыть

Берегите себя
  • ❤ 15
  • 🔥 11
  • 😁 6
  • 🤔 1
Post #121 581
Жизнь научила меня не смешивать разные изменения в одном PR

Фичи, багфиксы, рефакторинг — у этих изменений разный контекст и разный уровень риска. Бывает, сядешь за новую фичу, и видишь, отрефакторить бы немного, тогда фича отлично ляжет. Ну рефачишь, по дороге еще какой-то баг обнаружил в соседней фиче, его поправил, заливаешь пулрик на 1к строк с этим всем. В чём проблема?

Сложно одновременно всё ревьюить (разные контексты) но вам об этом ревьюеры и так скажут. Или будут морозить неделю, потому что такой PR читать лень. Но это не главное.

Вот вас кое-как оревьюили, тестеры протестировали, выкатили на прод. Бум! Какая-то проблема проскочила все защиты и надо срочно откатывать. Тоже не проблема — мы же умные, роллбечим релиз.

Но в мастере-то код сломан. И следующий релиз будет сломан. Тут головняк пропорционален частоте ваших релизов. Надо мастер тоже чинить. Быстрее всего — ревертнуть. Но как? Допустим, проблема в той новой фиче, и откатить нужно именно её. Но вы в том же PR ещё багу починили, отревертите тот PR — бага вернётся. А ещё рефакторинг сделали (разный уровень риска). А ваши коллеги может уже понаписали там что-то поверх, будете ревертить — конфликтов не оберётесь. Короче, удачи.

А если бы вы в трёх отдельных PR сделали то же самое, ревертнули бы только фичу. Опенсорс тоже говорит об этом, вспомните React 18.3. Они там прямо говорят, что к предыдущей версии они добавили лишь ворнинги для подготовки к react 19. Чтобы обеспечить 3-шаговое обновление:

Шаг 1: Обновляетесь до 18.3 — если вы были на 18.2, то код совместим
Шаг 2: Чините все ворнинги и deprecations — короче активно шатаете кодовую базу
... тут вы даже можете пожить с этим какое-то время и убедиться что всё ок ...
Шаг 3: Обновляетесь до 19.0 — это должно пройти практически бесшовно, если вы на шаге 2 всё починили
сгорел прод? ну откатываете версию, а код не надо трогать

То же самое при внедрении новых правил линтеров:
1. Сначала приводите код в соответствие правилу
2. Потом врубаете его на всех

Это перекликается с идеей Branch by abstraction из TBD. Там большие изменения не могут долго жить в отдельной ветке. Их дробят на маленькие безопасные шаги, которые можно быстро влить и быстро откатить.

О чём надо себя спросить перед открытием PR: как я буду в случае чего это ревертить?
  • 🔥 7
  • ❤ 4
Post #120 521

Forwarded from code_cleanup

Привет, а вот и новое видео!

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

А конкретно:
— выносим бизнес-логику из React компонента
— разбираемся с концепцией derived state
— используем селекторы в Zustand
— пишем тесты 💚 на стор без React и DOM
— и даже ловим классическую ошибку с getSnapshot в Next.js

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

Получился почти час 😅 наливайте чайку и залетайте к нам

https://youtu.be/oKbi-K2kj4Q
YouTube Code Cleanup #3: Stop Putting Business Logic in React Components (Zustand Selectors Explained) Managing state in React often leads to components full of business logic — filtering, sorting, pagination, and other derived data living directly in the UI. In this video, we refactor a real React application using Zustand and show how to move business logic…
  • 🔥 6
  • ❤ 2
Post #119 604
Layers vs Vertical Slices

Кирилл Мокевнин (Hexlet) набросил, как файлы класть — по типу или по домену?

Для меня меня на фронтенде это вопрос давно решенный: если сервис больше чем 2 странички, то, конечно, по фичам. Иначе, чтобы поправить какую-то мелочь, надо по 5 папкам лазить.

📗 Главный принцип: low coupling, high cohesion

Недавно был на проекте: 90к строк кода, 4 фронтендера. Код разложен по слоям: consts, utils, hooks, api, components, pages. Так там утилит было на ~20к строк (четверть кодовой базы!), в них лежала почти вся логика приложения. В константах лежало 202 файла. Тип пропсов компонента из src/components/statistics/CohortsTable.tsx лежал в src/types/statistics/CohortsTable.d.ts. Постоянные проблемы с циклическими зависимостями. Ребята генерили новый код, похожий на старый — трудно было найти нужное.

Когда в ру-язычной фронтенд-тусовке говорят про vertical slices, вспоминают FSD. Имхо, челы перегибают палку. Зачем деление на widgets/features/entities? Это тащит нас обратно — в low cohesion, high coupling. Поэтому туда не ходим, keep it simple, stupid.

И вот мы пару недель обсуждали, какие есть проблемы, почему больно это поддерживать, почему даже мелкие задачки занимают столько времени. В итоге проблема «хз че где» вышла на первое место по скору ICE (Impact × Confidence × Ease).

Мы выработали структуру и правила. Самое сложное было — выделить доменные сущности, об этом никто раньше не думал. Ещё за неделю раскидали 80% файлов, жить сразу стало легче. Подробнее писал в блоге компании (опубликовали в мой последний день там лол)

В src осталось три папки:
• app — рутовый компонент, провайдеры
• features — самая соль по доменам
• shared — общие компоненты

В каждой фиче (опционально): pages, ui, store, api, utils, const, types. При этом если какие-то константы, типы или хелперы нужны только для одного компонента, они идут в папку этого компонента. На уровень фичи поднимается только то, что нужно для нескольких модулей в ней.

Один коллега боялся, что пути/будут/вот/такие/длинные/ужас/кошмар. Но .../ui/Component это последний левел глубины. Внутри компонента всё плоско. Если меньше 10-15 файлов в папке, доп. уровни не нужны:

src/features/apps/ui/AppsTable/
AppsTable.tsx
AppsTable.module.css
DesktopRow.tsx
MobileRow.tsx
CellWrapper.tsx
useColumns.tsx
formatter.ts


Дальше учимся давать имена сущностям из вонючего ящика utils и выделять их из файлов по тыще строк. Типовые куски:

• adapters/mappers — из ответов API в структуру, удобную для фронтенда и обратно — обычно в src/features/<feature>/api
• validators — валидаторы/схемы для формочек — к соотв. компоненту
• formatters — как мы даты форматируем и т.п. — к компоненту

Выкидываем barrel-файлы (index.ts с реэкспортами) из папок, которые не являются модулями:

• src/features/apps/ui/AppsTable — модуль (компонент), кладём index.ts, реэкспортируем «публичный интерфейс» — скорее всего, это сам <AppsTable /> и его пропсы. А всякую внутреннюю шелуху типа форматтеров или useColumns не реэкспортим
• src/shared/routing — модуль, кладём index.ts, реэкспортируем всякие константы маршутов, функции для их построения и тп
• src/features/apps/ui/ — не модуль, а просто папочка организационная

👉 Писал про barrel-файлы у себя в блоге.

Откуда я знал, что всё это сработает? Потому что уже строил такую архитектуру на проекте в Яндексе, который был крупнее, и мы жили так пару лет и всё отлично работало и скейлилось. Сейчас, посмотрев на проекты в других компаниях, понимаю, что dev experience на этом проекте был лучшим.

Зачем мы 2 недели обсуждали, если я сразу «знал, как надо»? Чтобы:
• провалидировать, что это решит проблемы именно текущего проекта, и именно самые больные
• адаптировать подход к проекту и команде, срезать углы, что-то улучшить
• ребята вовлеклись и участвовали в принятии решения, люди гораздо лучше делают то, что решили сами, чем что-то навязанное

Кстати, AI-агентам в такой структуре проще ориентироваться.

А вы в каком лагере?
🔥 features first: src/features/<feature>/ui
🤔 layers first: src/ui/<feature>/blabla
⭐️ уже иду рефакторить
  • 🔥 13
  • ❤ 2
Post #117 368
Структура файлов на проекте, импорты, barrel файлы. Пост ниже ↓
  • 🤔 1
Post #116 615

Forwarded from code_cleanup

Неужели мы выпустили видео? Конечно выпустили!

Ну и шляпу там нам AI нагенерил, сортировка пузырьком. Рефакторим по TDD, максимально упрощая логику. Объясняем, в чём прикол разных локалей при сортировке.

Улучшили качество видео. Пока мы ещё не супер-блоггеры, но стремимся!

Энджой, лайк, подписка

https://youtu.be/rTbZ38qX_6Q
YouTube Code Cleanup Ep 2: Building Bidirectional Sorting with Locale Support Learn how to replace inefficient O(n²) bubble sort with JavaScript's built-in Timsort algorithm for better performance and cleaner code. In this episode, we refactor a contact sorting function using test-driven development and modern JavaScript best practices.…
  • ❤ 10
  • 👍 2
  • 🔥 1
Post #115 743
isqualog • front-end • productivity Photo
Мифы про отличия Zustand и Redux

Работаю сейчас с zustand, который уже обогнал redux по загрузкам. Вот что говорят адепты zustand, сравнивая его с redux:

Миф 1: В Zustand можно создавать множество сторов вместо одного!

По факту и правда можно, но в доке Zustand советуют «single store». А если мол ваше приложение большое, можете разделить стор на слайсы.

В redux тоже single store, который можно разделить на слайсы. И в отличие от zustand, есть встроенное решение для динамической подгрузки слайсов, что позволяет делать код-сплиттинг и загружать только нужные слайсы.

Миф 2: В Zustand меньше бойлерплейта!

По факту и правда меньше, пока у тебя стор размером с "counter, increment, decrement". Как только тебе надо обновить поле где-то глубоко в дереве:

updateNestedParam: (value: string) => {
set((state) => ({
deep: {
...state.deep,
nested: {
...state.deep.nested,
obj: { ...state.deep.nested.obj, param: value }
}
}
}))
}


В то время как в redux уже давно можно просто:

updateNestedParam: (state: MyState, value: string) => {
state.deep.nested.obj.param = value
}


Чтобы решить эту проблему документация zustand советует нам immer. На этой библиотеке как раз работает redux, просто она уже встроена. А с zustand нужно писать всё вручную. Есть ещё опция прикрутить immer middleware, чтобы получилось ну-вот-уже-почти-как-в-redux, только вместо одной функции надо две писать:

updateNestedParam: (value: string) => {
set(state => {
state.deep.nested.obj.param = value
})
}


Миф 3: Ура, не нужно использовать Provider!

И правда не нужно. А это точно преимущество? Чтобы написать тесты на компонент, использующий redux, нужен враппер с preloadedState. В Zustand советуют мокать (!) методы самого zustand, чтобы добавить в каждый стор метод очистки, и вызывать это в afterEach — а что если мне в тесте нужен не initialState, а какой-то уже наполненный. Опять всё руками? ЛИБО, внимание, использовать Context API, чтобы предоставить компонентам конкретный инстанс стора. В чём разница с Redux Provider?

Миф 4: Zustand лучше перфоманс!

И показывают бенчмарки на батчевую запись в стор, где в redux используется immer, а в zustand его не добавляют, и пишут тот самый бойлерплейт из мифа №2. Мы точно сравниваем полноценные решения на реальном юз-кейсе? Или подгоняем задачу под ответ?

Я повидал разные проекты. Вопрос производительности библиотек встаёт на масштабах главной страницы Яндекса, где сам код приложения уже оптимизирован донельзя. Проекты поменьше, даже если там сложные графики с 5-летними данными с дневной гранулярностью (зачем), или формы с 200 селектами (зачем), тормозят не из-за стейт-менеджера, а из-за того, как написано само приложение.

Миф 4.1: В Zustand селекторы более гранулярные, именно это влияет на перфоманс!

В zustand можно так:

useMyStore(state => state.very.deep.object.prop)


Но в redux можно точно также:

useSelector(state => state.very.deep.object.prop)


В чём разница? Получили ли мы что-то новое в Zustand, или авторы просто строят очередной Redux?
  • ❤ 8
  • 🔥 7
  • 🤔 4
  • 😱 2
  • 👎 1
Post #114 523
  • 🤔 1
Post #113 722
Толщина рамок в уголках

10+ лет в индустрии, и вот снова неделю крашу кнопки. Файн-тюним дизайн-систему на проекте.

Знаете же эти модные кнопки и плашки с градиентными рамками? Обычно это два элемента: «задний» с градиентным фоном выглядывает из-за «ближнего» элемента с белым фоном (ну или какой там фончик).

Если делать одинаковый border-radius у внутреннего и внешнего элемента, то уголки как бы утолщаются, выглядит не аккуратно. Верхний блочок на скрине, видите?

То ли дело, если уменьшить радиус внутреннего элемента на толщину рамки! Второй блочок на скрине выглядит прилично.

Поясняю в числах:

1. У блока с градиентом радиус 20px, толщина рамки 5px. Тогда у «белого» элемента радиус должен быть 15px.

2. У блока с градиентом радиус 10px, толщина рамки 2px. Тогда у «белого» радиус должен быть 8px.

Код и пример: https://codepen.io/isqua/pen/vEGomyr?editors=1100

Узнали? Согласны? 😁
  • 👍 16
  • 😁 6
  • 🔥 3
Post #112 875
В моей команде есть несколько ex-google инженеров. От них я узнал, что у Гугла есть публичные (!) гайдлайны по дизайну API. Называется «Google AIPs: API Improvement Proposals»

👉 https://google.aip.dev/

Вот несколько примеров документов:

AIP-193: Errors — формат ошибок, куда писать код ошибки, куда сообщение, локализацию, и как передать доп. информацию.

AIP-234: Batch methods: Update — батчевые ручки. Что должны отвечать синхронные и асинхронные апдейты и как сигнализировать, что только часть данных обновилась успешно. Отдельный поинт что батчевые ручки (и вообще кастомные операции) называются через двоеточие, типа
/users:batchUpdate

AIP-164: Soft delete — удаление и восстановление, в каких API-методах удалённые сущности могут и не могут появляться, и как же их всё-таки получить. И что делать, если восстановление долгое.

Там есть пропозалы и по клиентам для этих API. Короче, интересный справочник!
  • 🔥 11
  • 👍 6
  • ❤ 1
  • 😁 1
Post #109 859
Не поверите, на днях переубедил дизайнера

Делаем тёмную тему для сервиса. У нас дашборд с карточками, и фон конечно светло-серый, а карточки белые. И когда светлая тема выверена, хочется просто инвертировать палитру серых и бахнуть тёмную тему.

Что выходит, когда мы просто инвертируем цвета? Темно-серый фон и черные карточки. То есть в светлой теме карточки были парящими над фоном островами, а в тёмной теме они получаются... дырками.

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

Я не сам это выдумал: чекнул Gmail, там чётко видно, как повторили «направление света». И тёмный режим в айфоне, там тоже красиво.

Вот нарисовал вам карточки для наглядности! Хотите пошарить своему англоязычному дизайнеру? Скидывайте ссылку на linkedin.
  • 👍 24
  • 😁 1
  • 🤔 1
Post #108 1.41K
Приходит ко мне однажды Алёна Батицкая, та самая, из Доки, и говорит «а что, слабо нам видео про рефакторинг выпускать?» и я такой «ну нинаю, ну надо пробовать»

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

А потом всё сожгли и выпустили пилотный выпуск на 7 минут про то, как оторвать useState в формах на React 19.

Поддержите нас пожалуйста лайками и репостами в твиттере и linkedin. И конечно смотрите наш выпуск!

https://youtu.be/JdMGSgh9uHA
YouTube Code Cleanup Ep 1: Refactoring forms with React 19 features In this first episode of Code Cleanup, Alena and Alex refactor a simple contact form using new features from React 19. Together, we replace boilerplate `useState` logic with native form behavior. The result is shorter, cleaner, and faster code with fewer…
  • ❤ 10
  • 🔥 10
Post #107
isqualog • front-end • productivity pinned «Привет! Я Алекс, Senior Software Engineer. В 2014-м пришёл в Яндекс джуном, дорос до тимлида и откатился в разработчики. В 2024-м переехал в Европу, сейчас работаю в стартапах. Стек: React, TypeScript, Node.js. Официально я фронтендер, но что я только ни…»
Older posts →

About this channel

How can I read @isqualog without a Telegram account?
TGViewer shows the public web preview Telegram publishes for isqualog • front-end • productivity: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does isqualog • front-end • productivity have?
isqualog • front-end • productivity (@isqualog) has 586 subscribers on Telegram, refreshed roughly every 30 minutes.
Does isqualog • front-end • productivity know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →