Лысый чел | Николай Гущарин


Kanal geosi va tili: Rossiya, Ruscha
Toifa: Bloglar


Блог разработчика из БигТеха.
В основном личные наблюдения, переживания и, конечно, про технологии.
Статейки - https://baldman.justsquad.su
Менторство - https://getmentor.dev/mentor/nikolay-gusharin-4557

Bog‘liq kanallar

Kanal geosi va tili
Rossiya, Ruscha
Toifa
Bloglar
Statistika
Postlar filtri




Так, к чему же был прошлый пост?👀

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

И вот мы заходим к ней на чай, и я замечаю какой-то постоянный фоновый шум. Оказалось, она через Яндекс Алису включает "белый шум", чтобы ребёнок лучше засыпал.

Я начал изучать вопрос и обнаружил, что это не просто бабушкин метод — есть научные исследования. Белый шум работает как акустическая маскировка: он перекрывает резкие внешние звуки (лай собаки, хлопок двери), которые иначе будят. А розовый шум, кстати, статистически близок к природным звукам — шуму дождя, листвы на ветру, прибоя. Многие люди находят его субъективно комфортнее.😲

Но запись на Яндекс Музыке может быть неточной, и у меня родилась безумная идея: собрать свой генератор шума на ESP32 — с возможностью удалённого управления через Home Assistant.
Пошёл в Qwen, описал задачу — он расписал весь набор компонентов. Заказал на Али и Озоне... и забросил проект на 4 месяца.

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

Осталось самое сложное — корпус. Но зато получится не только интересный продукт, но и практика в написании embedded-решений на Rust.🤗


Video oldindan ko‘rish uchun mavjud emas
Telegram'da ko‘rish
Оно живое! ЖИВОЕ!!😭


Жиза ИТ руководителя dan repost
Год назад я стал руководителем команды в @ozon_tech. Проект получил большую порцию новых контекстов. Ему нужны были фичи, а мне — люди. Поэтому я одновременно писал код, прорабатывал новую архитектуру и проводил собеседования. Пять-шесть интервью в неделю, и это не считая ревью и синков.

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

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

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

А потом пришёл к команде с умным видом:

— Смотрите, вот тут же можно было сделать вот так. И вот тут. И вообще, у нас в кодовой базе такое…

А мне в ответ:

— Да мы на такие куски постоянно натыкаемся. Глядим, кто автор — а там везде ты.

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


Как НЕ надо подключать СХД к компуктеру

Сегодня речь пойдет про DAS хранилище, которое подключается к миниПК по usb.
В комплекте поставки с устройством шел кабель usb-c usb-c. Но набор разъемов у ПК позволяет подключать только usb-a.

Попробовал использовать различные кабели, которые были дома в наличии, в том числе новомодные дорогие на 100w.
Но они не заработали. Устройство даже не появлялось среди доступных. Поэтому решил просто попробовать заиспользовать переходник с type-c на type-a. Я его когда-то покупал на али, и он вроде шел как высокоскоростной. В этом конфигурации даже заработало… но, не совсем все.

Диски монтировались, работали, но через время отключались. Искал в интернетах, спрашивал у робота, использовал разные подходы. Даже создал крон Джону, которая диск опрашивает раз в 10 минут, чтобы он не засыпал, но все равно, он отключался даже при постоянном использовании (например при прослушивании музыки)

В итоге психанул, заказал именно usb3.2 gen2 кабель. И, о чудо, все работает и уже сутки как не пропадает подключение.🤗

Мораль - каждая мелочь важна😒


Что то меня уже замучили сервисы Яндекса.

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

У нас семейная подписка, и там типа прописано 10 устройств. В семью можно добавить до 4 человек. Т.е. +-2-3 устройства на человека. Что как бы мало в современном мире. И людей есть планшеты, телефоны, телевизоры.
Так ещё они иногда считают подключение 2х сервисов на одном устройстве (например книги и музыка) как 2 подключения😱

И меня что то уже так стало раздражать вся эта свистопляска с отключением, переключением и другими манипуляциями🤗

На телефоне теперь открываются книги, но не открывается музыка…
Короче решил искать альтернативу музыкальному сервису.
Пока делаю упор на self hosted решении.

Развернул navidrome. Теперь другая проблема - наполнить коллекцию музыки


Route 256 получил приставку 😀☺️🙄

Пишу об этом, потому что знаю изнутри: это не инициатива «для галочки». Помню, как мы запускали самый первый поток Route 256 по C#: мы с коллегами тратили кучу времени на шлифовку каждой лекции и семинара, чтобы дать максимум пользы.

Откуда суффикс Pro? Этот интенсив только для тех, у кого есть от 3 лет коммерческого опыта. Никаких основ, базовых знаний и синтетических задачек.

В этом наборе два трека:
☀️ Углубленная Go-разработка - в масштабах архитектуры ozon
☀️ Комплексная DS-инженерия

Как всё устроено:
3⃣ недели образовательного контента
1⃣ неделя дискуссий с экспертами Ozon Tech
2⃣ недели на разработку реального проекта

Всё онлайн и, по доброй традиции, бесплатно.

🔗 Подробнее и регистрация 👉 тут

Сам бы с удовольствием записался на 🧑‍💻-трек, чтобы освежить некоторые архитектурные паттерны. Но, во-первых, 🧑‍💻 я так и не выучил (всё руки не доходят), а во-вторых, сейчас на работе больше «болтаю», валидирую архитектуру и координирую команды, чем пишу код. Хотя по вечерам стараюсь не забрасывать практику.

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

Если будут вопросы по формату изнутри — пишите в комменты, постараюсь подсказать.
Кстати дедлайн 31 июля🤗


Всем привет😭

Уверен, что все уже сильно соскучились. Меня снова накрыл творческий кризис на фоне работы и ситуаций вокруг. Но уже несколько человек спросили почему в канале пусто и почему нет сообщений, так что пора возвращаться.

За время отсутствия произошло несколько изменений на работе. Наше направление расширяется. Создалась новая команда, которая будет усиливат проект. Наша команда расширилась на одну позицию. Теперь будет аж 6 BE разработчиков на 1 FE и на 2 QA. Теперь появляется перекос в сторону BE и поэтому нужно будет по другому планировать работы.
В рабочих задачах решили более активно использовать внутренних кодовых агентов, хотя бы для написания документации и генерации новых идей. Получается даже не совсем плохо.

Из личных проектов.
Тоже решил приобщиться к обществу вайбкодеров🤗 купил подписку на Клод. Решил сделать приложение для учета проектов на 3д принтере. Получилось сносно, даже с дизайном интерфейса. Позже продемонстрирую результат.

А ещё на день рождение ребята на работе подарили DAS (коробка для ЖД) и диск на 4ТБ (Wd red plus) теперь воплощаю свою старую мечту - создание своего облачного хранилища для фото и файлов. Для фотографий пока выбрал приложение Immich, сейчас настраиваю монтирование дисков и синхронизацию с устройствами.

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

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


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

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

А когда начались проблемы с телегой, то тут стало совсем печально. По большому счету, я пока не нашел альтернативы. Макс мне не понравился как продукт, примерно как с вотсапом, не удобно им пользоваться. Какие то другие аналоги не имеют такого функционала, как в тг.

Еще грустнее, что вот только только начал делать несколько продуктов под тг мини аппы, а теперь появляется ощущение, что опаздал…

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

Надо дальше думать что делать. И канал не хочется терять. И будто переходить некуда

А у вас какие мысли? Какую альтернативу выбрали?😕

124 0 0 16 11

Ozon Tech dan repost
Ozon Tech Community .NET Meetup

24 марта, лофт Casa Picassa, 18:30

Ищем способы бороться с primitive obsession, отличать OrderID от ItemID, переживать нагрузку без каскадных отказов с load shedding и спасаться от аллокаций с помощью JIT-оптимизатора ❕

➡И находим: вас ждут три доклада — немного про runtime-внутрянку, немного про хайлоад-сервисы, много-много кейсов из нашей .NET-практики.

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

Есть ощущение, что места закончатся через 3…2…1…
Так что не тяните с регистрацией ⬅️

#ozontech_events #csharp


OzonTech открывает сезон митапов и конференций 2026 года

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

Регистрируйтесь и приходите🕺


Беспощадные гонки или как смотреть на это с Optimistic. Часть 2.

Проблемы с фоном и фронтендом 💻

⚡️Фронтенд:
Не надейтесь, что фронтендеры сами вспомнят про версии.
Решение: Положите версию прямо в DTO ответа и требуйте её в DTO запроса. Заголовки (ETag) хороши для REST, но в GraphQL/gRPC проще передать версию явно в поле.

⚡️UX:
Если получили 409 — не просто пишите «Ошибка». Покажите дифф: «Данные изменились пока вы редактировали. Вот что изменилось. Перезаписать?».

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

⚡️ Фоновые процессы (Jobs/Consumers):

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

Когда OCC — это зло?🆘

Оптимистичная блокировка не панацея.

▪️ Высокая конкуренция: Если на одну запись пишут 100 потоков в секунду (например, бронирование мест на концерт), вы получите шторм исключений и постоянные retry. Тут нужен пессимизм (SELECT FOR UPDATE) или очередь (очередь команд на изменение).

▪️ Длинные транзакции: Если пользователь держит форму открытой часами, версия устареет гарантированно. Тут нужны механизмы слияния изменений (merge), а не просто перезапись.

Итог:

OCC — часто является обязательным требованием при реализации api с конкурентным доступом. Это дешевле, чем разгребать последствия потерянных заказов, и проще, чем городить очереди на каждое изменение.

А как у вас решаются проблемы конкурентности? Или вы предпочитаете просто оставить все как есть и придерживаться принципа «кто последний тот и папа»?

#dotnet #architecture #backend


Беспощадные гонки или как смотреть на это с Optimistic. Часть 1.

Классическая ситуация: два менеджера одновременно открыли карточку товара. Один изменил цену, другой — описание. Второй нажал «Сохранить» на секунду позже. Изменения первого перезаписаны.

Добро пожаловать в «Проблему потерянных обновлений»

В микросервисной архитектуре на это лечится несколькими способами. Но мы сегодня поговорим не про блокировки со стороны базы (пессимизм), а про Optimistic Concurrency Control (OCC) и про то…

Почему это важно для DDD? 🧠

В предметно-ориентированном проектировании Агрегат — это границца консистентности. Мы гарантируем, что внутри агрегата данные согласованы.
Если вы не используете OCC, вы фактически позволяете внешнему миру нарушать инварианты вашего агрегата в момент сохранения.

У нас в проектах команды OCC используется везде, где есть запись данных пользователем. И де-факто мы считаем это уже стандартом (хотя иногда начинает подгорать)

Как реализовать в .NET стеке? 🛠

Есть несколько основных путей, и они часто ходят вместе:

1⃣На уровне БД.

Чтобы не создавать отдельное поле под версионирование можно использовать RowVersion (timestamp) в SQL Server или xmin в PostgreSQL.

public class Order {
public int Id { get; set; }
public uint Version { get; set; } // Конкурентный токен
}
// В DbContext: modelBuilder.Entity().Property(x => x.Version).IsConcurrencyToken();
xmin по определению это счетчик транзакции, он автоинкрементируемый. И если в одной транзакции меняется сразу несколько отношений то каждое из них получит одинаковое значение версии.
А если вам, помимо решения проблемы с конкурентностью, хочется отслеживать версию отношения, то выгоднее использовать отдельную колонку. Но тогда вся логика по контролю и обновлению ляжет на ваши плечи.

При сохранении объекта в запросе нужно проверять текущее значение версии и новое, и если они не совпадают выбрасывать DbUpdateConcurrencyException

2⃣ На уровне бизнес логики

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

3⃣ На уровне API. При общении в потребителями

➕ Ответ сервера: Возвращайте ETag: "v123" в заголовках или поле version в DTO.

➕ Запрос клиента: Клиент обязан отправить If-Match: "v123" или поле version в теле запроса.

➕ Бэкенд: Сравнивает версию сущности с пришедшей. Не совпадает? → 409 Conflict.

Продолжение в следующей части...🦶


Последние две недели даются поистине сложно...😑

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

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

Но можно отметить несколько приятных моментов из этих переработок. Чтобы успеть закатить одну инициативную задачу, мы три вечера плотно посидели, и представили ее бизнесу. А интересная она потому, что смогли заиспользовать функционал AI моделей, которые развернуты в контуре. Так сказать, прикоснулись к современным технологиям для улучшения процессов. Бизнес был в восторге, а мы были усталыми. Но довольными за полученный результат. 😓

Что касается ревью, откровенно, положа руку на сердце, этот процесс мне не нравится. Есть в нем... некая доля не прозрачности. И невозможно нормально прогнозировать то, что будет в итоге. Ты можего работать, впахивать, и не факт что получишь которую ожидаешь. А меня, как руководителя это расстраивает. Потому что по факту не получается в должной мере поощрить своих ребят, так как есть ограничения. Подробнее про процесс можно почитать в бесконечных отзывах и статьях про компанию. Понятное дело, что у каждого свое мнение, кому то нравится, кто-то видит в этом поистине здравый процесс, но не все.

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

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

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


🏡 Про развитие умного дома

Home Assistant был установлен почти сразу после окончания ремонта.
Я уже рассказывал про интеграции и модули, которые удалось внедрить — но до сих пор не покидает ощущение, что использую его не на полную мощность.
А тут, холодным зимним вечером, снова забыл, когда в последний раз меняли воду в поилке у котиков — и задумался:
Почему, имея отдельный сервер умного дома, я до сих пор не настроил автоматизацию для напоминаний?

Быстро загуглил — и оказалось, что всё гораздо проще, чем я думал.

В Home Assistant есть специальный раздел — «Вспомогательные инструменты» (Helpers), где можно создавать объекты почти любого типа:
⭕️input_datetime — для хранения даты/времени,
⭕️input_number — для периода в днях,
⭕️template sensor — чтобы вычислять разницу и красиво отображать на дашборде.

Используя эти инструменты я создал объекты:
🔘поле с датой последней замены воды,
🔘поле с периодом напоминания (например, 3 дня),
🔘сенсор, считающий дни до следующего события,
🔘и автоматизацию, которая отправляет push-уведомление на мобильные устройства, когда пришло время действовать.

По тому же принципу сделал ещё несколько напоминалок — как раз те, что видны на скриншоте.
Например, фильтры для воды… Давненько не менялись. Точную дату установки не помню🤗, поэтому поставил ориентир от даты переезда. Но, судя по всему, их пора менять уже сейчас.📱

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

Есть среди нас ещё энтузиасты, которые любят «заморачиваться» с умным домом?
Какие самые полезные или неожиданные автоматизации вам удалось внедрить? Или, может, модули, без которых теперь не представляете жизнь?

#HomeAssistant #умныйдом #автоматизация


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

Невозможно исключить той вероятности, что после «правильного» DDD ваш сервис стал… медленнее?
🐢

С такой ситуацией может столкнуться любая команда. Рассмотрим ситуацию, у вас есть домен поставок товаров. И вот вы выделяете агрегат Supply (поставка). Но какова ценности поставки, если у нее не будет состава. Значит создается entity SupplyItem и он включается в сам агрегат. Но как же можно управлять составом напрямую без поставки? Конечно нельзя, поэтому мы запрещаем прямой доступ и начинаем грузить агрегат целиком — даже чтобы просто обновить статус поставки.

Результат?
🅰️ 120 мс на чтение данных по поставке (из-за eager-загрузки всех позиций),
🅰️ блокировки на уровне БД при параллельных операциях,
🅰️ и вечный спор: «Но это же нарушает инварианты!»

Знакомо?

💯 Проблема не в DDD. Проблема — в референциальной непрозрачности

Когда вы проектируете агрегат, вы думаете:

«Пусть он будет единым целым — тогда я гарантированно сохраню инварианты».


Но в реальности:
➖ Агрегаты растут (10+ коллекций),
➖ Операции разные (одни читают, другие пишут, третьи — только один флаг),
➖ А вы всё равно грузите 90% данных, которые не нужны.

И вот вы платите цену целостности за операции, где она не требуется.

Это — DDD-тормоз.


✅ Как можно это починить (без переписывания архитектуры)

1️⃣ Разделить "чтение" и "запись" внутри агрегата

Да, звучит как CQRS. Но локально — внутри одного сервиса.

Можно оставить единый SupplyAggregate для команд, но для частых read-only операций стали использовать проекции:

// Вместо:
var supply = await _supplyRepository.GetById(id);
return supply.Status;

// Делаем:
var status = await _supplyProjection.GetStatus(id);
Проекция — это просто SQL-запрос (или Dapper-маппинг) напрямую в нужную таблицу.
Без загрузки всего агрегата. Без риска нарушить инвариант.

2️⃣ Ввести понятие "частичной загрузки"
Не все операции требуют полного агрегата.
Для обновления статуса поставки нам не нужны позиции, история прохождения по точкам, комментарии и еще много чего

Можно создать методы вроде:

public async Task LoadForStatusUpdate(Guid supplyId)
{
// Загружаем только: ID, Status, SupplyInfo
}
3️⃣ Попробовать перестать бояться "нарушить инвариант" там, где он не важен
Инвариант «статус не может быть “доставлен”, если нет трек-номера» — важен при смене статуса.
Но чтение текущего статуса — не должно зависеть от этого.

Если операция не меняет состояние — она не обязана проходить через полный агрегат.

💡Какой можно сделать вывод

DDD — это про защиту инвариантов при изменении состояния.

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

Вы можете:
✏️ Использовать полный агрегат для сложных бизнес-операций (RecreateSupply, SplitSupply CancelSupply),
✏️ И использовать лёгкие проекции или частичные загрузки для простых задач (GetStatus, UpdateTrackingNumber).

Так вы сохраняете семантику DDD — и производительность системы.

P.S. Нет, это не «DDD наполовину». Это DDD с учётом реальности.
Потому что в проде важны не только чистые модели — но и latency, throughput и стабильность.

А вы сталкивались с «тяжёлыми агрегатами»? Как выходили из ситуации?

#ddd #dotnet #architecture #performance #backend


📘 Прошлый год был просто революционным. Прочитал целых две книги 😂 Давно такого не было.
И одна из них - «Идеальный руководитель. Почему им нельзя стать и что из этого следует» — Ицхак Адизес.

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

Хочу поделиться одним главным выводом — особенно для тех, кто, как я, ведёт команду инженеров, пишет код, даёт менторские сессии и при этом пытается «всё держать под контролем».

Идеального техлида не существует. И это — хорошая новость.


Через всю книгу, красной линией, проходит утверждение, что у руководителя есть четыре роли:
1️⃣ P — делать результат (Producer)
2️⃣ A — следить за порядком (Administrator)
3️⃣ E — видеть будущее (Entrepreneur)
4️⃣ I — объединять людей (Integrator)

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

Например, представим лидера, который легко генерирует идеи (E) и закрывает сложные задачи (P).
Но тяжело следит за процессами (A) и слабо поддерживает эмоциональную атмосферу (I). Это не характеризует его как «плохого лидера», а значит что это не его естественные роли.

И вместо того чтобы «прокачивать себя» в этих зонах до изнеможения, нашему лидеру нужно начать строить систему, где:
⭕️ член команды с хорошо прокаченными знаниями архитектуры заберёт ответственность за A
⭕️ один из senior-инженеров может забрать I роль (менторство, onboarding, обратная связь)
⭕️ а лидер может сосредоточиться на том, что даётся легко — и где его вклад максимальный

Результат?
Команда станет стабильнее. Лидер — спокойнее. А проекты — предсказуемее.

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


Если вы чувствуете, что «всё держится на вас» — возможно, вы просто ещё не нашли тех, кто закроет ваши слабые роли.
А может, даже не позволили им проявиться.

P.S. В следующих постах разберем, как это применять на практике — от найма до архитектурных решений.
А пока — подумайте: какие 1–2 роли из PAEI ваши? А какие вы «тянете через силу»?

#менеджмент #техлид #leadership #адизес


12 января. День «а надо ли?»📱

Сегодня официально страна выходит на работу после 12 дней праздников, а я почти после месяца отдыха.
Да-да, я тот редкий зверь, который взял отпуск до Нового года — две недели, плюс 12 дней праздников... В итоге последний раз думал о Jira где-то в середине декабря.

За это время:

☀️ Отдыхали в Тайланде — 12 дней солнца, моря и морепродуктов. Местность очень красивая. Особенно понравился климат и тот факт, что там среднегодовое изменение продолжительности дня составляет всего один час. Другими словами, солнышко и летом и зимой восходит и заходит примерно в одно и тоже время!
🚘 Объездил всю округу — традиционный новогодний тур по родственникам, вернулись домой только 5-го;
😀 Полностью отключился от работы — ни одного PR’а (именно рабочего), ни одного созвона, даже MM не открывал (это почти преступление 😅).

И знаете, что странно?
Я не скучал по задачам, дедлайнам и архитектурным дилеммам. Совсем.
Но по команде — очень. У нас просто отличные люди: умные, ответственные, с чувством юмора 🤣. Без них рабочие будни теряют половину смысла.

А ещё за это время голова начала думать не про баги, а про возможные возможности.
В частности — про пассивный доход. Не в смысле «купить акции и забыть», а в смысле «создать что-то, что работает, пока ты спишь».
Долго крутится идея вокруг 3D-печати — и вот, принтер уже стоит на столе. Пока напечатали только рамку для фотографии, но планируем осваивать мелкосерийное производство: может быть штучки для умного дома, или элементы интерьера, или системы хранения (например всякой мелочевки для гаража). Если у вас есть идеи или заказы — пишите, попробуем реализовать 😊

Ну и конечно, составил план на 2026.
Он амбициозный. Возможно, наивный. Но без плана — только реактивное проживание. А хочется двигаться осознанно. Расскажу о нём позже — когда станет понятно, насколько он реалистичен.

А пока — глубокий вдох, чашка кофе и медленное погружение обратно в код, Kubernetes и DDD-дискуссии.🔥
Если вы тоже сегодня с трудом заставляете себя включиться — знайте: вы не одни.❤️

А завтра будет легче. Обещаю.😬


Вот и закончился отпуск — пора возвращаться к обычной жизни…😓
Но как же здорово брать отпуск прямо перед праздниками! Ведь впереди ещё почти две недели, чтобы заниматься своими делами и не вспоминать о рабочих проблемах.😀

Сегодня дошли руки до обновления темы на сайте, где я собираю свои статьи.
Как уже упоминал, для этого ресурса использую статический генератор Zola. Одна из его сильных сторон — экосистема пользовательских тем: любой может создать и поделиться своим оформлением.

Раньше я использовал abridge — отличная, гибко кастомизируемая тема. Но всё равно чего-то не хватало.

На этот раз решил попробовать tabi — в итоге она мне больше понравилась по стилистике.
Плюс приятный бонус: из коробки поддерживается модуль комментариев.
Из доступных вариантов выбрал giscus — он работает на базе GitHub Discussions, полностью клиентский, без трекинга и с хорошей интеграцией.
Теперь у всех есть возможность оставлять комментарии к постам и делиться мыслями о прочитанном 💬

Обновлённый дизайн доступен по прежней ссылке:
👉 https://baldman.justsquad.su/


Async/await в .NET — золото или яд? Как лучше писать асинхронный код 💥

Давайте взглянем на достаточно простой метод:

public async Task ProcessCheckoutAsync(Guid orderId)
{
var order = await _orderService.GetAsync(orderId);
var payment = await _paymentService.ProcessAsync(order);
var shipping = await _warehouseService.ReserveAsync(payment);
await _analytics.FireAsync(order);
await _notifications.SendAsync(order);
return await _mapper.MapAsync(shipping);
}


Код читается легко, понятно:
🔵 получаем данные по заказу
🔵 проводим проводку
🔵 оформляем резерв на складе
🔵 на финальном этапе отправляем уведомление и скидываем данные в аналитику.

(Тут пока не будем обращать внимание на отсутствие обработки ошибок, ретраях, аутбоксах и тд)

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

Вот что происходило в реальности:

🔵 _orderService.GetAsync() → ~80 мс
🔵 _paymentService.ProcessAsync() → ~200 мс
🔵 _warehouseService.ReserveAsync() → ~100 мс
🔵 _analytics.FireAsync() → ~30 мс (и не зависит от payment!)
🔵 _notifications.SendAsync() → ~40 мс (тоже не зависит от payment!)

Но из-за линейной цепочки общая latency = 80 + 200 + 100 + 30 + 40 = 450 мс.

А могло быть так:
🔵 Запускаем _orderService.GetAsync() → ждём 80 мс.
🔵 Как только получили order — запускаем payment + analytics + notifications одновременно (они не зависят друг от друга).
🔵 Как только payment завершился → запускаем shipping.

Тогда:
➕ 80 мс (order)
➕ max(200 мс (payment), 30 мс (analytics), 40 мс (notifications)) = 200 мс
➕ 100 мс (shipping)
🟰 итого ~380 мс

Экономия ~70 мс — это ~15%, но в реальном сервисе может быть ещё 2–3 side-эффекта:
🔸 обновление кэша в Redis,
🔸 отправка события в Kafka,
🔸 запись в локальный audit-log.

Все они не блокируют основной поток, но из-за линейного await’а — тянут общее время.

С учетом этих зависимостей, можно переписать код следующим образом:


public async Task ProcessCheckoutAsync(Guid orderId)
{
// Шаг 1: получаем заказ
var order = await _orderService.GetAsync(orderId);

// Шаг 2: запускаем ВСЁ, что можно — параллельно
var paymentTask = _paymentService.ProcessAsync(order);
var analyticsTask = _analytics.FireAsync(order);
var notificationTask = _notifications.SendAsync(order);
var cacheUpdateTask = _cache.InvalidateUserCartAsync(order.UserId);
var auditLogTask = _audit.LogAsync($"Checkout initiated for {orderId}");

// Ждём payment — он критичен для shipping
var payment = await paymentTask;

// Шаг 3: резервируем склад
var shipping = await _warehouseService.ReserveAsync(payment);

// Шаг 4: дожидаемся остального (они уже почти завершены)
await Task.WhenAll(analyticsTask, notificationTask, cacheUpdateTask, auditLogTask);

return await _mapper.MapAsync(shipping);
}


Результат:
💥 Средняя latency упала с 450 мс до 270 мс.
💥 P95 — с 1.2 с до 650 мс.
💥 Это ~40% ускорение на практике, особенно под нагрузкой, где side-эффекты начинают «накладываться».

О чем может говорить этот пример?
Async/await не даёт параллелизма сам по себе. Он лишь позволяет не блокировать поток, но вызовы всё равно выполняются последовательно, если не используется Task.WhenAll или явный запуск задач.

Какое правило можно взять на вооружение?
Перед тем как писать цепочку await’ов — нарисуй граф зависимостей.
Всё, что не зависит от результата предыдущего вызова — запускай параллельно.

20 ta oxirgi post ko‘rsatilgan.