Alternatives to pre-commit package in python development
In my opinion, pre-commit package is often misused and I want to show you an alternative way.
Read here: https://shiriev.ru/posts/2024-12-14-pre-commit-in-python/
In my opinion, pre-commit package is often misused and I want to show you an alternative way.
Read here: https://shiriev.ru/posts/2024-12-14-pre-commit-in-python/
Asyncio tasks can be canceled, but asyncio provides a way to shield tasks from cancellation via asyncio.shield().
Read here more: https://shiriev.ru/posts/2025-01-30-asyncio-shield/
Read here more: https://shiriev.ru/posts/2025-01-30-asyncio-shield/
Artur's Blog
Shielding from cancellation in asyncio
Introduction Asyncio tasks can be canceled. For example, when application is shutting down.
This can cause a running task to stop mid-execution, which can cause problems if we expect a task to complete as an atomic operation.
Asyncio provides a way to shield…
This can cause a running task to stop mid-execution, which can cause problems if we expect a task to complete as an atomic operation.
Asyncio provides a way to shield…
👍1
About strict-mode in mypy.
This article describes some problems which can be faced after turning on strict mode in Mypy and proposes solutions to them.
Read here: https://shiriev.ru/posts/2025-02-07-strict-mypy/
This article describes some problems which can be faced after turning on strict mode in Mypy and proposes solutions to them.
Read here: https://shiriev.ru/posts/2025-02-07-strict-mypy/
Artur's Blog
Strict Mypy
Mypy - Static type checker that aims to combine the benefits of dynamic and static typing
The article is about journey from
[tool.mypy] python_version = "3.11" warn_return_any = false warn_unused_configs = true ignore_missing_imports = true strict_optional…
The article is about journey from
[tool.mypy] python_version = "3.11" warn_return_any = false warn_unused_configs = true ignore_missing_imports = true strict_optional…
I have recently migrated some projects from poetry to uv and used this tool https://github.com/stvnksslr/uv-migrator. Take a look if you have some poetry projects and consider moving them to uv
How to install and run on MacOS:
1. Install cargo. For this I installed rust by running
2. Install
3. Run command in the root directory of your project:
Here is what came out of it https://github.com/community-of-python/microbootstrap/blob/main/pyproject.toml
How to install and run on MacOS:
1. Install cargo. For this I installed rust by running
brew install rust2. Install
uv-migrator:cargo install uv-migrator3. Run command in the root directory of your project:
uv-migrator .Here is what came out of it https://github.com/community-of-python/microbootstrap/blob/main/pyproject.toml
GitHub
GitHub - stvnksslr/uv-migrator: tool for migrating to the uv package manager
tool for migrating to the uv package manager. Contribute to stvnksslr/uv-migrator development by creating an account on GitHub.
When using FastAPI with redirect_slashes=True (the default setting), POST requests to endpoints without trailing slashes are redirected to their slash-appended versions. However, this redirect process can cause unexpected behavior where POST requests are converted to GET requests, potentially leading to data loss and incorrect endpoint handling.
I solved this by turning off such redirects completely by settings redirect_slashes argument to False:
I solved this by turning off such redirects completely by settings redirect_slashes argument to False:
from fastapi import FastAPI
app = FastAPI(redirect_slashes=False)
🔥3
Сегодня пост не про технологии.
Недавно размышлял и анализировал свой профессиональный путь и путь коллег и пришел к некоторым умозаключениям, как расти до сеньора и выше.
В общем виде сформулировал идею так: не разделяйте работу на зоны ответственности.
Допустим, у меня, как у разработчика, возникла проблема, которая не связана непосредственно с разработкой. Например, перестали работать ci-пайплайны.
Я отношусь к этому, как к своей проблеме, которую нужно решить мне. Я могу попросить коллег о помощи, но это по-прежнему моя ответственность, чтобы убрать блокер.
Если в будущем можно как-то избежать или минимизировать возможность появления проблемы, то я предприму меры: заведу задачу, напишу статью и т.д.
Какие преимущества у такого подхода:
1. Я прокачиваю свои коммуникативные и организаторские навыки, так как для решения каких-то особенно сложных проблем может потребоваться подключить много разных людей из разных команд.
2. Я прокачиваю смежные профессиональные навыки и начинаю видеть общую картину, что позволит мне в будущем брать на себя более сложные задачи.
3. Мой руководитель понимает, что со мной не нужен микроменеджмент и я не буду сидеть без дела, потому что столкнулся с проблемой "не из моей зоны ответственности". У него повысится уровень доверия ко мне и он начнет мне доверять более сложные задачи и может порекомендовать к повышению.
Для себя сформулировал следующий вывод: отсутствие компетенции не освобождает меня от ответственности.
P.S. я расту именно так, но не утверждаю, что это гарантированный и самый эффективный способ
P.P.S и я не имею в виду, что любую проблему я должен решать собственноручно. Я про то, что если подключу других людей, то как минимум буду держать эту проблему в фокусе и постоянно мониторить ее решение
Недавно размышлял и анализировал свой профессиональный путь и путь коллег и пришел к некоторым умозаключениям, как расти до сеньора и выше.
В общем виде сформулировал идею так: не разделяйте работу на зоны ответственности.
Допустим, у меня, как у разработчика, возникла проблема, которая не связана непосредственно с разработкой. Например, перестали работать ci-пайплайны.
Я отношусь к этому, как к своей проблеме, которую нужно решить мне. Я могу попросить коллег о помощи, но это по-прежнему моя ответственность, чтобы убрать блокер.
Если в будущем можно как-то избежать или минимизировать возможность появления проблемы, то я предприму меры: заведу задачу, напишу статью и т.д.
Какие преимущества у такого подхода:
1. Я прокачиваю свои коммуникативные и организаторские навыки, так как для решения каких-то особенно сложных проблем может потребоваться подключить много разных людей из разных команд.
2. Я прокачиваю смежные профессиональные навыки и начинаю видеть общую картину, что позволит мне в будущем брать на себя более сложные задачи.
3. Мой руководитель понимает, что со мной не нужен микроменеджмент и я не буду сидеть без дела, потому что столкнулся с проблемой "не из моей зоны ответственности". У него повысится уровень доверия ко мне и он начнет мне доверять более сложные задачи и может порекомендовать к повышению.
Для себя сформулировал следующий вывод: отсутствие компетенции не освобождает меня от ответственности.
P.S. я расту именно так, но не утверждаю, что это гарантированный и самый эффективный способ
P.P.S и я не имею в виду, что любую проблему я должен решать собственноручно. Я про то, что если подключу других людей, то как минимум буду держать эту проблему в фокусе и постоянно мониторить ее решение
❤6👍1
В команде для общения пользуемся корпоративным mattermost, раньше пользовались Slack.
Самая крутая для меня фича Slack'а - это треды. Сегодня хочу рассказать о том, какими принципами руководствуюсь при работе с тредами.
1. Один тред - одна проблема
Если в треде начинают обсуждать какие-то вопросы, не связанные с изначальной темой, то я попрошу завести новый тред или сам инициирую новый тред.
Преимущества:
1. Если в тред нужно будет пригласить нового участника, то у него не будет перед глазами лишнего контекста
2. Если для нового обсуждения нужны не все участники, то в новом тред можно пригласить только тех, кого он касается
2. Чем писать в старый тред, лучше создать новый
Бывает так, что обсудили какую-то тему и после паузы нужно продолжить общение. Вместо того, чтобы написать в старый большой тред, я создаю новый, в котором кратко излагаю контекст из старого треда и добавляю новый контекст.
Преимущества:
1. Участникам не нужно перечитывать весь тред
2. Инициатор освежает в голове контекст, что ведет к более продуктивной дискуссии
3. Отписываюсь от "завершенных" тредов
Что считаю "завершенным" тредом
1. Если обсуждаемый вопрос в треде полностью разрешился
2. Если обсуждаемый вопрос оформлен в виде задачи
3. Если по треду нет активности 2 и более дней (субъективно)
На "завершенный" тред ставлю реакцию с галкой и отписываюсь от него.
Реакция галки для других участников означает, что если нужно переоткрыть данный тред, то есть ненулевая вероятность, что участники треда отписались от него и нужно "упоминание" / "mention", т.е. явный призыв в тред
Преимущества:
1. Таким образом количество тредов не разрастается до бесконечности и можно периодически пробегаться по списку и трекать статус каких-то обсуждений
4. Треды вместо личных сообщений
Если кто-то написал в личные сообщения по рабочим вопросам, то я по возможности перевожу обсуждение в тред
Преимущества:
1. В тред можно на любой стадии призвать новых участников и они легко погрузятся в контекст
2. Повышается прозрачность и вся команда находится в общем контексте
5. Треды - не документация
Если итоги обсуждения в треде представляют ценность в будущем, то должен появится какой-то артефакт: задача, статья или что-то еще. Треды не могут стать базой знаний команды.
Самая крутая для меня фича Slack'а - это треды. Сегодня хочу рассказать о том, какими принципами руководствуюсь при работе с тредами.
1. Один тред - одна проблема
Если в треде начинают обсуждать какие-то вопросы, не связанные с изначальной темой, то я попрошу завести новый тред или сам инициирую новый тред.
Преимущества:
1. Если в тред нужно будет пригласить нового участника, то у него не будет перед глазами лишнего контекста
2. Если для нового обсуждения нужны не все участники, то в новом тред можно пригласить только тех, кого он касается
2. Чем писать в старый тред, лучше создать новый
Бывает так, что обсудили какую-то тему и после паузы нужно продолжить общение. Вместо того, чтобы написать в старый большой тред, я создаю новый, в котором кратко излагаю контекст из старого треда и добавляю новый контекст.
Преимущества:
1. Участникам не нужно перечитывать весь тред
2. Инициатор освежает в голове контекст, что ведет к более продуктивной дискуссии
3. Отписываюсь от "завершенных" тредов
Что считаю "завершенным" тредом
1. Если обсуждаемый вопрос в треде полностью разрешился
2. Если обсуждаемый вопрос оформлен в виде задачи
3. Если по треду нет активности 2 и более дней (субъективно)
На "завершенный" тред ставлю реакцию с галкой и отписываюсь от него.
Реакция галки для других участников означает, что если нужно переоткрыть данный тред, то есть ненулевая вероятность, что участники треда отписались от него и нужно "упоминание" / "mention", т.е. явный призыв в тред
Преимущества:
1. Таким образом количество тредов не разрастается до бесконечности и можно периодически пробегаться по списку и трекать статус каких-то обсуждений
4. Треды вместо личных сообщений
Если кто-то написал в личные сообщения по рабочим вопросам, то я по возможности перевожу обсуждение в тред
Преимущества:
1. В тред можно на любой стадии призвать новых участников и они легко погрузятся в контекст
2. Повышается прозрачность и вся команда находится в общем контексте
5. Треды - не документация
Если итоги обсуждения в треде представляют ценность в будущем, то должен появится какой-то артефакт: задача, статья или что-то еще. Треды не могут стать базой знаний команды.
🔥3
Сегодня хочу рассказать, как я работаю с почтой.
У меня есть 3 почтовых ящика: 2 личных и один рабочий. И во всех этих ящиках 0 входящих сообщений. И в спаме тоже пусто. Обычно есть менее 5 сообщений в архиве, это могут быть билеты на самолет, поезд.
Как я этого добиваюсь
- Я регулярно отписываюсь от рассылок, которые мне больше не интересны или на которые я вообще не подписывался
- Большую часть писем я сразу удаляю
- Если письмо подразумевает какое-то короткое действие на пару минут, то я его сразу делаю: оплатить квитанцию, провести ревью кода, ответить на письмо
- Если письмо требует больше времени, то я могу создать задачу, перенести туда весь нужный контекст, а письмо удалить
- Если в письме есть какая-то полезная информация, то я нахожу ей месте своей системе хранения
- Бывает, что по работе что-то ломается и это порождает уведомления на рабочий ящик. Я обычно являюсь тем, кто чинит это, чтобы уменьшить поток сообщений.
Какие преимущества такого подхода
- По работе я всегда остаюсь в курсе происходящего в команде
- Я не пытаюсь найти какую-то информацию в почтовом ящике, так как она вся уже обработана и лежит там, где она может потребоваться
- Когда старые письма не мелькают перед глазами, то гораздо проще обрабатывать новые сообщения
Пример 1
Я недавно уходил в отпуск на полторы недели. За это время мне прилетело 600+ сообщений. Их полная обработка заняла полтора часа и после этого я был полностью в контексте задач, которыми моя команда занималась. Провел ревью всего написанного кода, оставил свои комментарии, завел необходимые задачи и инициировал необходимые обсуждения в чатах.
Пример 2
Даже когда я не был лидом, благодаря этой технике просматривал весь код, который писала команда. И всегда был в контексте происходящего на проекте, был в курсе проблем, с которыми столкнулись коллеги и был вооружен, если сам сталкивался с такими проблемами.
Инвестиция в пустой список входящих окупается с лихвой, поэтому настоятельно рекомендую попробовать.
У меня есть 3 почтовых ящика: 2 личных и один рабочий. И во всех этих ящиках 0 входящих сообщений. И в спаме тоже пусто. Обычно есть менее 5 сообщений в архиве, это могут быть билеты на самолет, поезд.
Как я этого добиваюсь
- Я регулярно отписываюсь от рассылок, которые мне больше не интересны или на которые я вообще не подписывался
- Большую часть писем я сразу удаляю
- Если письмо подразумевает какое-то короткое действие на пару минут, то я его сразу делаю: оплатить квитанцию, провести ревью кода, ответить на письмо
- Если письмо требует больше времени, то я могу создать задачу, перенести туда весь нужный контекст, а письмо удалить
- Если в письме есть какая-то полезная информация, то я нахожу ей месте своей системе хранения
- Бывает, что по работе что-то ломается и это порождает уведомления на рабочий ящик. Я обычно являюсь тем, кто чинит это, чтобы уменьшить поток сообщений.
Какие преимущества такого подхода
- По работе я всегда остаюсь в курсе происходящего в команде
- Я не пытаюсь найти какую-то информацию в почтовом ящике, так как она вся уже обработана и лежит там, где она может потребоваться
- Когда старые письма не мелькают перед глазами, то гораздо проще обрабатывать новые сообщения
Пример 1
Я недавно уходил в отпуск на полторы недели. За это время мне прилетело 600+ сообщений. Их полная обработка заняла полтора часа и после этого я был полностью в контексте задач, которыми моя команда занималась. Провел ревью всего написанного кода, оставил свои комментарии, завел необходимые задачи и инициировал необходимые обсуждения в чатах.
Пример 2
Даже когда я не был лидом, благодаря этой технике просматривал весь код, который писала команда. И всегда был в контексте происходящего на проекте, был в курсе проблем, с которыми столкнулись коллеги и был вооружен, если сам сталкивался с такими проблемами.
Инвестиция в пустой список входящих окупается с лихвой, поэтому настоятельно рекомендую попробовать.
🔥3👏1
Еще мысли про развитие.
Если в каком-то обсуждении вижу что-то неизвестное: какой-то непонятный термин, аббревиатуру, что угодно, то стараюсь выяснить и стать более осведомленным в этом вопросе.
1. Если есть время и силы, то сразу ищу информацию: в интернете, в базах знаний и т.д.
2. Если информацию не нашел или это специфичная информация, то задаю вопросы людям, которые могут мне ответить или подсказать, где искать ответы на мои вопросы.
3. Если нет сил или времени выяснять сразу, то записываю в блокнот. Записи в блокноте периодически разбираю: либо сразу ищу информацию, либо завожу задачи. При создании заметок и задач важно добавлять побольше контекста: это может быть важно, чтобы понять, где лучше начать поиски.
Преимущества данного подхода:
1. Быстрая адаптация на новом месте работы. Когда я только прихожу в новую компанию, возникает очень много вопросов, но если активно уменьшать неопределенность, то адаптация происходит гораздо быстрее
2. Быстрое развитие профессиональных навыков. Благодаря данному подходу можно открывать для себя много новых возможностей для роста. Это важно для развития, как архитектора или лида. Это прокачивает так называемый технический кругозор (Technical Breadth)
3. Если обсуждения происходят в публичных чатах, то это и еще источник развития для всей команды, потому что у других людей тоже могут возникать те же самые вопросы, но они стесняются их задавать.
Если в каком-то обсуждении вижу что-то неизвестное: какой-то непонятный термин, аббревиатуру, что угодно, то стараюсь выяснить и стать более осведомленным в этом вопросе.
1. Если есть время и силы, то сразу ищу информацию: в интернете, в базах знаний и т.д.
2. Если информацию не нашел или это специфичная информация, то задаю вопросы людям, которые могут мне ответить или подсказать, где искать ответы на мои вопросы.
3. Если нет сил или времени выяснять сразу, то записываю в блокнот. Записи в блокноте периодически разбираю: либо сразу ищу информацию, либо завожу задачи. При создании заметок и задач важно добавлять побольше контекста: это может быть важно, чтобы понять, где лучше начать поиски.
Преимущества данного подхода:
1. Быстрая адаптация на новом месте работы. Когда я только прихожу в новую компанию, возникает очень много вопросов, но если активно уменьшать неопределенность, то адаптация происходит гораздо быстрее
2. Быстрое развитие профессиональных навыков. Благодаря данному подходу можно открывать для себя много новых возможностей для роста. Это важно для развития, как архитектора или лида. Это прокачивает так называемый технический кругозор (Technical Breadth)
3. Если обсуждения происходят в публичных чатах, то это и еще источник развития для всей команды, потому что у других людей тоже могут возникать те же самые вопросы, но они стесняются их задавать.
🔥6
Сегодня расскажу, как управляю историями и задачами в тасктрекере (Jira)
Организация историй и задач
- Истории – это контейнеры для задач:
- Бизнес-истории (фичи, улучшения для пользователей).
- Технические истории (долг, инфраструктура, эксперименты).
- Задачи – конкретные шаги для реализации истории.
- Активно используем на проекте связи между элементами:
-
-
Подготовка к спринту: ревизия и планирование
Перед началом спринта анализирую:
- Фильтр "Истории в работе" (активный спринт):
- Если история не завершена → создаю задачи-продолжения в следующий спринт.
- Для бизнес-историй: приоритет – минимизировать незавершенную работу.
- Для технических историй: добавляю небольшие задачи в каждый спринт (постепенное движение).
- Если история завершена → передаю на тестирование или закрываю.
- Фильтр "Все истории":
- Оцениваю долгосрочные инициативы, проверяю актуальность.
- Удаляю или архивирую устаревшее.
Работа с зависимостями
- Блокировки всегда отражаю в Jira:
- Если задача
- Если задача
Общие принципы
- Гибкость: Не создаю все задачи сразу – только по мере необходимости.
- Прозрачность: Все зависимости должны быть видны команде.
- Регулярность: Даже небольшие шаги по тех. долгу лучше, чем его игнорирование.
Такой подход помогает держать фокус на завершении работы, избегать "зависших" задач и поддерживать баланс между бизнес- и техническими целями.
Организация историй и задач
- Истории – это контейнеры для задач:
- Бизнес-истории (фичи, улучшения для пользователей).
- Технические истории (долг, инфраструктура, эксперименты).
- Задачи – конкретные шаги для реализации истории.
- Активно используем на проекте связи между элементами:
-
consists of – история включает задачи. -
blocks / is blocked by – явное указание зависимостей. Подготовка к спринту: ревизия и планирование
Перед началом спринта анализирую:
- Фильтр "Истории в работе" (активный спринт):
- Если история не завершена → создаю задачи-продолжения в следующий спринт.
- Для бизнес-историй: приоритет – минимизировать незавершенную работу.
- Для технических историй: добавляю небольшие задачи в каждый спринт (постепенное движение).
- Если история завершена → передаю на тестирование или закрываю.
- Фильтр "Все истории":
- Оцениваю долгосрочные инициативы, проверяю актуальность.
- Удаляю или архивирую устаревшее.
Работа с зависимостями
- Блокировки всегда отражаю в Jira:
- Если задача
A зависит от B → связь is blocked by. - Если задача
X блокирует историю Y → связь blocks. Общие принципы
- Гибкость: Не создаю все задачи сразу – только по мере необходимости.
- Прозрачность: Все зависимости должны быть видны команде.
- Регулярность: Даже небольшие шаги по тех. долгу лучше, чем его игнорирование.
Такой подход помогает держать фокус на завершении работы, избегать "зависших" задач и поддерживать баланс между бизнес- и техническими целями.
🔥2
🧪 Разработка через тесты — мой основной подход
Я редко запускаю сервисы локально. Вместо этого:
1. Пишу код или его часть.
2. Добавляю тесты, которые используют эту логику.
3. Через breakpoint’ы проверяю корректность выполнения.
4. Повторяю, пока весь код не будет готов и покрыт тестами.
Это не чистый TDD (тесты до кода), но тесты пишутся параллельно с кодом для быстрой проверки.
🔥 Преимущества:
✔️ Быстрая обратная связь – тесты работают быстрее, чем ручной вызов API.
✔️ Надёжность – логика сразу покрыта тестами, меньше багов.
✔️ Изоляция от внешних зависимостей – можно замокать ответы.
📌 Как тестирую API?
Раньше думал, что нужно много API-тестов, но теперь так:
🔹 Логика выносится в
🔹 Основные тесты пишутся на них, а не на API.
🔹 API-тесты остаются минимальными – только проверка успешного сценария.
✅ Почему так лучше?
▪️ Бизнес-правила тестируются без привязки к HTTP.
▪️ Логику можно переиспользовать в других местах.
▪️ Рефакторинг становится проще.
📝 Итог:
1. Тесты + код без постоянного локального запуска = быстрее и надежнее.
2. Основной фокус – на сервисы и use cases, а не на API.
3. API-тесты проверяют только контракт.
А у вас как организовано тестирование? Что работает лучше всего?
Я редко запускаю сервисы локально. Вместо этого:
1. Пишу код или его часть.
2. Добавляю тесты, которые используют эту логику.
3. Через breakpoint’ы проверяю корректность выполнения.
4. Повторяю, пока весь код не будет готов и покрыт тестами.
Это не чистый TDD (тесты до кода), но тесты пишутся параллельно с кодом для быстрой проверки.
🔥 Преимущества:
✔️ Быстрая обратная связь – тесты работают быстрее, чем ручной вызов API.
✔️ Надёжность – логика сразу покрыта тестами, меньше багов.
✔️ Изоляция от внешних зависимостей – можно замокать ответы.
📌 Как тестирую API?
Раньше думал, что нужно много API-тестов, но теперь так:
🔹 Логика выносится в
services или use cases. 🔹 Основные тесты пишутся на них, а не на API.
🔹 API-тесты остаются минимальными – только проверка успешного сценария.
✅ Почему так лучше?
▪️ Бизнес-правила тестируются без привязки к HTTP.
▪️ Логику можно переиспользовать в других местах.
▪️ Рефакторинг становится проще.
📝 Итог:
1. Тесты + код без постоянного локального запуска = быстрее и надежнее.
2. Основной фокус – на сервисы и use cases, а не на API.
3. API-тесты проверяют только контракт.
А у вас как организовано тестирование? Что работает лучше всего?
👍4
В uv теперь есть собственный бэкенд для сборки пакетов
Уже перевел часть пакетов на него и попутно выпилил hatch-vcs (использовался для версионирования на основе тегов в git).
Вот так подключается build backend
Также по-умолчанию uv ищет пакет в src/{имя пакета}. Чтобы искать в корне, нужно добавить:
В CI теперь uv используется и для проставления версии, и для сборки, и для загрузки пакета на PYPI:
Более детально с изменениями можно ознакомиться здесь https://github.com/modern-python/lite-bootstrap/pull/41
Уже перевел часть пакетов на него и попутно выпилил hatch-vcs (использовался для версионирования на основе тегов в git).
Вот так подключается build backend
[build-system]
requires = ["uv_build"]
build-backend = "uv_build"
Также по-умолчанию uv ищет пакет в src/{имя пакета}. Чтобы искать в корне, нужно добавить:
[tool.uv.build-backend]
module-name = "lite_bootstrap"
module-root = ""
В CI теперь uv используется и для проставления версии, и для сборки, и для загрузки пакета на PYPI:
uv version $GITHUB_REF_NAME
uv build
uv publish --token $PYPI_TOKEN
Более детально с изменениями можно ознакомиться здесь https://github.com/modern-python/lite-bootstrap/pull/41
👍5
Про чтение документации 📚
Существует такое мнение, что чтение документации - это не очень эффективное использование времени. В корне не согласен с этим.
Если я внедряю в проект новый инструмент, библиотеку или фреймворк, то обязательно нахожу время, чтобы прочитать его документацию обычно *уже после* первоначальной интеграции.
Почему именно после? Потому что, уже имея практический опыт, я понимаю контекст и вижу, как неочевидные фичи могут решить мои реальные задачи.
Что это дает?
Я постоянно нахожу «скрытые жемчужины» — возможности, которые были упущены при первом знакомстве. Это не просто новые методы, а целые концепции, которые могут кардинально упростить код, повысить его производительность или надежность.
Примеры из моей практики:
•
•
Сейчас в процессе изучения документации
Как я применяю этот подход?
Я не просто читаю. Я действую по алгоритму:
1. Читаю с включенным «режимом поиска»
2. Нахожу полезную фичу → сразу же оцениваю, где ее можно применить
3. Фиксирую: либо сразу вношу правку, либо создаю задачу, либо делаю заметку
Этот подход превращает документацию из справочника в источник вдохновения для обновления ваших проектов.
Резюме: Выделите время на вдумчивое чтение документации инструментов, которые вы уже используете. Это не трата времени, а инвестиция, которая окупается за счет более качественного, чистого и эффективного кода.
А вы часто находите что-то полезное, только когда углубляетесь в документацию?
Существует такое мнение, что чтение документации - это не очень эффективное использование времени. В корне не согласен с этим.
Если я внедряю в проект новый инструмент, библиотеку или фреймворк, то обязательно нахожу время, чтобы прочитать его документацию обычно *уже после* первоначальной интеграции.
Почему именно после? Потому что, уже имея практический опыт, я понимаю контекст и вижу, как неочевидные фичи могут решить мои реальные задачи.
Что это дает?
Я постоянно нахожу «скрытые жемчужины» — возможности, которые были упущены при первом знакомстве. Это не просто новые методы, а целые концепции, которые могут кардинально упростить код, повысить его производительность или надежность.
Примеры из моей практики:
•
Pydantic: Нашел способы валидации данных, о которых не знал, что позволило удалить много кастомного кода•
Polyfactory: Узнал о настройке __set_as_default_factory_for_type__, которая позволяет объявить фабрику дефолтной. Это помогло переопределить сложную схему для всех моделей, не прокидывая ее вручнуюСейчас в процессе изучения документации
FastStream и Litestar. И уже нашел отличный пример! В документации Litestar я наткнулся на фичу Channels. Это механизм для работы с Pub/Sub, который идеально подходит для отправки real-time данных от бэкенда клиентам — например, через Server-Sent Events (SSE) или WebSockets. Сейчас примеряю, как можно внедрить этот инструмент в рабочий проект.Как я применяю этот подход?
Я не просто читаю. Я действую по алгоритму:
1. Читаю с включенным «режимом поиска»
2. Нахожу полезную фичу → сразу же оцениваю, где ее можно применить
3. Фиксирую: либо сразу вношу правку, либо создаю задачу, либо делаю заметку
Этот подход превращает документацию из справочника в источник вдохновения для обновления ваших проектов.
Резюме: Выделите время на вдумчивое чтение документации инструментов, которые вы уже используете. Это не трата времени, а инвестиция, которая окупается за счет более качественного, чистого и эффективного кода.
А вы часто находите что-то полезное, только когда углубляетесь в документацию?
🔥6
Паттерны — это инструменты, а не трофеи. Или почему не стоит хотеть «применить сагу»
Как-то услышал от разработчика: «Хочу где-нибудь применить паттерн саги». Это вызвало недоумение.
Для меня сага — не цель, а вынужденная мера. Желание применить сложный паттерн — тревожный сигнал.
Что такое «Сага»?
📌 Паттерн для управления распределенными транзакциями в микросервисах
Используется когда:
• Длинная бизнес-транзакция не может быть выполнена атомарно
• Процесс затрагивает несколько сервисов со своими БД
• Нельзя использовать двухфазные коммиты (2PC)
Пример: оформление заказа
1. Сервис заказов → создает заказ (PENDING)
2. Сервис склада → резервирует товар
3. Сервис платежей → списывает деньги
4. Сервис доставки → инициирует доставку
Если платеж не прошел → откат шагов 2 и 1
Почему сага - «некрасивый» паттерн?
🚨 Сложность компенсаций
Код отката часто сложнее основной логики. Как «откатить» отправленное email-уведомление? Или физическую отправку посылки?
🚨 Распределенное состояние системы
Нужно хранить и отслеживать состояние всей саги:
• Оркестрация vs Хореография
• Надежное хранение состояния
• Таймауты и повторы
🚨 Ментальная нагрузка
Чтобы понять процесс «оформления заказа», нужно анализировать цепочку через 4-5 сервисов
Когда сага уместна?
Только когда без нее уже невозможно ✅
Осознанный выбор микросервисной архитектуры + распределенный бизнес-процесс = сага
Это плата за масштабируемость в распределенной системе
Что делать вместо?
💡 Сначала пишите простой и понятный код
💡 Выделяйте паттерны рефакторингом, а не предвосхищением
💡 Хорошая архитектура решает бизнес-задачи с минимальной сложностью
Если сага действительно нужна — система сама вам об этом скажет своей сложностью.
Как-то услышал от разработчика: «Хочу где-нибудь применить паттерн саги». Это вызвало недоумение.
Для меня сага — не цель, а вынужденная мера. Желание применить сложный паттерн — тревожный сигнал.
Что такое «Сага»?
📌 Паттерн для управления распределенными транзакциями в микросервисах
Используется когда:
• Длинная бизнес-транзакция не может быть выполнена атомарно
• Процесс затрагивает несколько сервисов со своими БД
• Нельзя использовать двухфазные коммиты (2PC)
Пример: оформление заказа
1. Сервис заказов → создает заказ (PENDING)
2. Сервис склада → резервирует товар
3. Сервис платежей → списывает деньги
4. Сервис доставки → инициирует доставку
Если платеж не прошел → откат шагов 2 и 1
Почему сага - «некрасивый» паттерн?
🚨 Сложность компенсаций
Код отката часто сложнее основной логики. Как «откатить» отправленное email-уведомление? Или физическую отправку посылки?
🚨 Распределенное состояние системы
Нужно хранить и отслеживать состояние всей саги:
• Оркестрация vs Хореография
• Надежное хранение состояния
• Таймауты и повторы
🚨 Ментальная нагрузка
Чтобы понять процесс «оформления заказа», нужно анализировать цепочку через 4-5 сервисов
Когда сага уместна?
Только когда без нее уже невозможно ✅
Осознанный выбор микросервисной архитектуры + распределенный бизнес-процесс = сага
Это плата за масштабируемость в распределенной системе
Что делать вместо?
💡 Сначала пишите простой и понятный код
💡 Выделяйте паттерны рефакторингом, а не предвосхищением
💡 Хорошая архитектура решает бизнес-задачи с минимальной сложностью
Если сага действительно нужна — система сама вам об этом скажет своей сложностью.
🔥4
Про техдолг
Недавно осознал, что техдолг по матрице Эйзенхауэра идеально живет в квадрате «✅ Важно, но не срочно». Пока он там, на него легко закрыть глаза. Но это мина замедленного действия.
Со временем он мигрирует в «🔥 Срочные и важные» проблемы, которые начинают:
▪️ Блокировать разработку
▪️ Срывать сроки
▪️ Создавать авралы и выгорание
🤔 Почему это ВАЖНО для РАЗРАБОТЧИКОВ?
В итоге мы платим за него самым ценным: своим временем, нервами и мотивацией. Работа превращается в борьбу с системой, которую мы же и создали.
📊 Почему это ВАЖНО для МЕНЕДЖЕРОВ?
▪️ Проект с техдолгом становится непредсказуемым. В любой момент может вылезти задача, которую уже нельзя отложить.
▪️ Система работает медленнее и менее стабильно, а попытки залатать дыры порождают новые.
💡 НАШ ОПЫТ: 3 года активной борьбы
На нашем проекте мы сознательно тратим на техдолг около 30% времени, а то и больше. И вот к каким результатам это привело за 3 года:
▪️ Снижение количества аварий. В первый год — десятки аварий, пару раз в месяц команда часами тушила пожары на проде. В этом году — всего 2 аварии, на которые мы не могли повлиять.
▪️ Снижение количества мелких инцидентов на проде, а значит — меньше рутины по их обработке.
▪️ 100% тестовое покрытие в большинстве сервисов. Большинство тестов — интеграционные. Они стабильны и переживают даже комплексные рефакторинги. Это дает уверенность.
▪️ Годовые цели закрываем на повышенные оценки, при этом бизнес-задачи растут, а размер команды — нет.
🎯 Наши ГЛАВНЫЕ ПРИНЦИПЫ
По работе с дефектами:
▪️ Zero-Bug Policy: количество открытых багов должно снижаться в долгосрочной перспективе.
▪️ Новые дефекты решаем в среднем за 1-2 спринта.
▪️ Старые баги периодически груммим и тоже закрываем.
▪️ Любой рефакторинг кода сопровождается рефакторингом тестов.
▪️ Починка дефектов всегда сопровождается написанием тестов.
▪️ После любой аварии — обязательная ретроспектива (хотя бы в треде) и фиксация мер. Задачи по ним берутся в работу в следующем спринте.
По зависимостям и тестам:
▪️ Зависимости в backend-сервисах обновляем практически с каждым MR.
▪️ Высокое покрытие тестами помогает сразу выявлять проблемы с обновлениями.
▪️ Если версию зависимости пришлось «залочить» — обязателен комментарий или ссылка на issue. Если issue нет — заводим.
▪️ Периодически делаем ревизию таких issue и пробуем обновиться.
⚠️ ПОДВОДНЫЕ КАМНИ (будьте готовы)
▪️ Первое время неизбежны проблемы из-за масштабных изменений. Но со временем их будет все меньше.
▪️ Растет нагрузка на QA. У нас это подсветило острую необходимость в автоматических e2e-тестах.
▪️ Бывали проблемные релизы, которые вставали только с 3-4 попытки. Чтобы митигировать риск, с самого начала задумайтесь о нагрузочном тестировании. Много проблем ловилось только на проде под нагрузкой.
🚀 ИТОГО
▪️ Работа с техдолгом крайне важна для любого активно развивающегося проекта. Иначе разработка просто встанет.
▪️ Эта работа невозможна без фокуса на тестировании:
• Интеграционные тесты для уверенного рефакторинга и обновлений.
• Нагрузочные тесты для выявления проблем до прода.
• E2E тесты для автоматизации и снижения нагрузки на QA.
• Каждый дефект по возможности сопровождается новыми тестами.
А как у вас обстоят дела с техдолгом?
Недавно осознал, что техдолг по матрице Эйзенхауэра идеально живет в квадрате «✅ Важно, но не срочно». Пока он там, на него легко закрыть глаза. Но это мина замедленного действия.
Со временем он мигрирует в «🔥 Срочные и важные» проблемы, которые начинают:
▪️ Блокировать разработку
▪️ Срывать сроки
▪️ Создавать авралы и выгорание
🤔 Почему это ВАЖНО для РАЗРАБОТЧИКОВ?
В итоге мы платим за него самым ценным: своим временем, нервами и мотивацией. Работа превращается в борьбу с системой, которую мы же и создали.
📊 Почему это ВАЖНО для МЕНЕДЖЕРОВ?
▪️ Проект с техдолгом становится непредсказуемым. В любой момент может вылезти задача, которую уже нельзя отложить.
▪️ Система работает медленнее и менее стабильно, а попытки залатать дыры порождают новые.
💡 НАШ ОПЫТ: 3 года активной борьбы
На нашем проекте мы сознательно тратим на техдолг около 30% времени, а то и больше. И вот к каким результатам это привело за 3 года:
▪️ Снижение количества аварий. В первый год — десятки аварий, пару раз в месяц команда часами тушила пожары на проде. В этом году — всего 2 аварии, на которые мы не могли повлиять.
▪️ Снижение количества мелких инцидентов на проде, а значит — меньше рутины по их обработке.
▪️ 100% тестовое покрытие в большинстве сервисов. Большинство тестов — интеграционные. Они стабильны и переживают даже комплексные рефакторинги. Это дает уверенность.
▪️ Годовые цели закрываем на повышенные оценки, при этом бизнес-задачи растут, а размер команды — нет.
🎯 Наши ГЛАВНЫЕ ПРИНЦИПЫ
По работе с дефектами:
▪️ Zero-Bug Policy: количество открытых багов должно снижаться в долгосрочной перспективе.
▪️ Новые дефекты решаем в среднем за 1-2 спринта.
▪️ Старые баги периодически груммим и тоже закрываем.
▪️ Любой рефакторинг кода сопровождается рефакторингом тестов.
▪️ Починка дефектов всегда сопровождается написанием тестов.
▪️ После любой аварии — обязательная ретроспектива (хотя бы в треде) и фиксация мер. Задачи по ним берутся в работу в следующем спринте.
По зависимостям и тестам:
▪️ Зависимости в backend-сервисах обновляем практически с каждым MR.
▪️ Высокое покрытие тестами помогает сразу выявлять проблемы с обновлениями.
▪️ Если версию зависимости пришлось «залочить» — обязателен комментарий или ссылка на issue. Если issue нет — заводим.
▪️ Периодически делаем ревизию таких issue и пробуем обновиться.
⚠️ ПОДВОДНЫЕ КАМНИ (будьте готовы)
▪️ Первое время неизбежны проблемы из-за масштабных изменений. Но со временем их будет все меньше.
▪️ Растет нагрузка на QA. У нас это подсветило острую необходимость в автоматических e2e-тестах.
▪️ Бывали проблемные релизы, которые вставали только с 3-4 попытки. Чтобы митигировать риск, с самого начала задумайтесь о нагрузочном тестировании. Много проблем ловилось только на проде под нагрузкой.
🚀 ИТОГО
▪️ Работа с техдолгом крайне важна для любого активно развивающегося проекта. Иначе разработка просто встанет.
▪️ Эта работа невозможна без фокуса на тестировании:
• Интеграционные тесты для уверенного рефакторинга и обновлений.
• Нагрузочные тесты для выявления проблем до прода.
• E2E тесты для автоматизации и снижения нагрузки на QA.
• Каждый дефект по возможности сопровождается новыми тестами.
А как у вас обстоят дела с техдолгом?
🔥5
Почему предпочитаю Sociable тесты
Sociable Test — это тест, который:
• Проверяет единицу поведения (unit of behavior), а не единицу кода (unit of code)
• Использует реальные зависимости (БД, кэш, HTTP-клиенты), а не заглушки (mocks, stubs)
🎯 Почему выбираю sociable тесты
1. Выявляют проблемы интеграции
Используются реальные зависимости → тестируют поведение, максимально приближенное к реальному
2. Отличная защита от регрессий
В отличие от solitary тестов, sociable тесты переживают изменения в коде и дают уверенность при рефакторинге.
Можно переписывать внутренности сервиса, и тесты останутся зелеными, пока не поменяется поведение.
3. Частичная замена интеграционным и E2E
• при использовании HTTP transport mocks проверяют контракты с другими сервисами (пример: respx для httpx) -> Могут заменять тесты на интеграции микросервисов между собой
• Усиливают или частично заменяют E2E-тесты, так как тестируют реальное поведение
⚡️ А как же недостатки?
• Медленнее?
Да, но один такой тест может заменить десяток мокированных, давая больше уверенности
• Сложнее настроить?
Да, нужна тестовая БД, контейнеры. Но это инвестиция в надежность
• Сложно покрыть все сценарии?
Можно использовать гибридный подход с заглушками для edge-кейсов
🛠 В каких случаях использую заглушки
• Для брокеров сообщений — проверяю, что отправлено правильное сообщение без реальной отправки
• Для сценариев, которые не покрыть чистыми sociable-тестами
• Для внешних зависимостей, уже протестированных за рамками тестируемого микросервиса
🎯 Мой подход — гибридный
Стремлюсь к максимально "чистым" Sociable-тестам и по необходимости использую заглушки.
Главное — фокус на поведении, а не на реализации!
Sociable Test — это тест, который:
• Проверяет единицу поведения (unit of behavior), а не единицу кода (unit of code)
• Использует реальные зависимости (БД, кэш, HTTP-клиенты), а не заглушки (mocks, stubs)
🎯 Почему выбираю sociable тесты
1. Выявляют проблемы интеграции
Используются реальные зависимости → тестируют поведение, максимально приближенное к реальному
2. Отличная защита от регрессий
В отличие от solitary тестов, sociable тесты переживают изменения в коде и дают уверенность при рефакторинге.
Можно переписывать внутренности сервиса, и тесты останутся зелеными, пока не поменяется поведение.
3. Частичная замена интеграционным и E2E
• при использовании HTTP transport mocks проверяют контракты с другими сервисами (пример: respx для httpx) -> Могут заменять тесты на интеграции микросервисов между собой
• Усиливают или частично заменяют E2E-тесты, так как тестируют реальное поведение
⚡️ А как же недостатки?
• Медленнее?
Да, но один такой тест может заменить десяток мокированных, давая больше уверенности
• Сложнее настроить?
Да, нужна тестовая БД, контейнеры. Но это инвестиция в надежность
• Сложно покрыть все сценарии?
Можно использовать гибридный подход с заглушками для edge-кейсов
🛠 В каких случаях использую заглушки
• Для брокеров сообщений — проверяю, что отправлено правильное сообщение без реальной отправки
• Для сценариев, которые не покрыть чистыми sociable-тестами
• Для внешних зависимостей, уже протестированных за рамками тестируемого микросервиса
🎯 Мой подход — гибридный
Стремлюсь к максимально "чистым" Sociable-тестам и по необходимости использую заглушки.
Главное — фокус на поведении, а не на реализации!
👍6❤1
💡 Про «Полярную звезду» (North Star Metric)
Недавно на обучении узнал про концепцию «Метрики Полярной звезды» (North Star Metric). Это ключевая метрика, которая лучше всего отражает ценность, которую ваш продукт или команда приносит клиентам. Она как путеводная звезда — все действия и решения можно сверять с ней: «Приближает ли это нас к цели?».
Я задумался: а какая «Полярная звезда» может быть у нашей команды, которая разрабатывает чат для общения клиентов банка со специалистами?
Интуитивно мы, как команда разработки, фокусировались на том, что видим и чем непосредственно управляем:
• Стабильность: Снижение количества аварий и инцидентов.
• Эффективность сопровождения: Уменьшение времени на разбор инцидентов, улучшение логирования, создание инструментов для диагностики.
Для удобства завели отдельную «историю» для идей от коллег по улучшениям и брали в среднем по задаче в спринт.
Далее я задал себе вопрос: «А эту ли ценность в итоге получают пользователи?».
Наши конечные пользователи — это:
1. Клиенты банка, которые получают помощь.
2. Специалисты банка, которые решают проблемы клиентов.
Их успех измеряется скоростью и качеством решения проблемы. Но команда чат-платформы не может напрямую влиять на компетенцию специалиста или сложность вопроса клиента.
Так где же наша настоящая «Полярная звезда»?
Наша ценность — не в том, чтобы система «не падала», а в том, чтобы не мешать диалогу и способствовать его эффективности. Сбои в чате — это крайняя степень «помех». Но есть и более тонкие.
Варианты «Полярной звезды» для команды платформы чата:
▪️ «Время доступности чата для диалога» — это более глубокая метрика, чем просто «аптайм». Она должна учитывать не только полные падения, но и периоды, когда нельзя отправить файл, загрузить историю, использовать виджет.
▪️ «Процент успешно завершенных сессий без технических сбоев». Сессия считается успешной с технической точки зрения, если не было разрывов соединения, потерь сообщений, недоступности обязательных функций (кнопки, история). Метрика направлена на ценность глазами пользователя: «смог ли я провести весь диалог так, как планировал».
🚨 Контрметрики, чтобы не застрять в прошлом
Выбрав такую «звезду», мы должны следить, чтобы оптимизируя ее, не убили развитие:
• Скорость выпуска фич: Количество/частота релизов. Если мы перестаем развивать продукт, мы проигрываем в долгосрочной перспективе.
• Здоровье кода: Регулярное обновление зависимостей, выполнение рефакторинга. Погоня за стабильностью любой ценой ведет к технологическому устареванию.
• Удовлетворенность внутренних пользователей: Их регулярный фидбек на новые функции и изменения в интерфейсе. Важно, чтобы платформа не только работала, но и была удобным инструментом.
🎯 Итог:
Наш интуитивный фокус на стабильности был важной компонентой, но не конечной целью. Настоящая «Полярная звезда» должна быть сформулирована на языке пользы для конечного пользователя диалога.
Возможно, для нас это «Процент успешных (без технических сбоев) диалогов». Все наши действия — от исправления багов и улучшения мониторинга до рефакторинга — должны быть направлены на увеличение этого процента. А контрметрики следят, чтобы мы, повышая его, не превратили чат в надежный, но устаревший инструмент.
А вы задумывались, какая "Полярная звезда" может быть у вашей команды? 🤔
Недавно на обучении узнал про концепцию «Метрики Полярной звезды» (North Star Metric). Это ключевая метрика, которая лучше всего отражает ценность, которую ваш продукт или команда приносит клиентам. Она как путеводная звезда — все действия и решения можно сверять с ней: «Приближает ли это нас к цели?».
Я задумался: а какая «Полярная звезда» может быть у нашей команды, которая разрабатывает чат для общения клиентов банка со специалистами?
Интуитивно мы, как команда разработки, фокусировались на том, что видим и чем непосредственно управляем:
• Стабильность: Снижение количества аварий и инцидентов.
• Эффективность сопровождения: Уменьшение времени на разбор инцидентов, улучшение логирования, создание инструментов для диагностики.
Для удобства завели отдельную «историю» для идей от коллег по улучшениям и брали в среднем по задаче в спринт.
Далее я задал себе вопрос: «А эту ли ценность в итоге получают пользователи?».
Наши конечные пользователи — это:
1. Клиенты банка, которые получают помощь.
2. Специалисты банка, которые решают проблемы клиентов.
Их успех измеряется скоростью и качеством решения проблемы. Но команда чат-платформы не может напрямую влиять на компетенцию специалиста или сложность вопроса клиента.
Так где же наша настоящая «Полярная звезда»?
Наша ценность — не в том, чтобы система «не падала», а в том, чтобы не мешать диалогу и способствовать его эффективности. Сбои в чате — это крайняя степень «помех». Но есть и более тонкие.
Варианты «Полярной звезды» для команды платформы чата:
▪️ «Время доступности чата для диалога» — это более глубокая метрика, чем просто «аптайм». Она должна учитывать не только полные падения, но и периоды, когда нельзя отправить файл, загрузить историю, использовать виджет.
▪️ «Процент успешно завершенных сессий без технических сбоев». Сессия считается успешной с технической точки зрения, если не было разрывов соединения, потерь сообщений, недоступности обязательных функций (кнопки, история). Метрика направлена на ценность глазами пользователя: «смог ли я провести весь диалог так, как планировал».
🚨 Контрметрики, чтобы не застрять в прошлом
Выбрав такую «звезду», мы должны следить, чтобы оптимизируя ее, не убили развитие:
• Скорость выпуска фич: Количество/частота релизов. Если мы перестаем развивать продукт, мы проигрываем в долгосрочной перспективе.
• Здоровье кода: Регулярное обновление зависимостей, выполнение рефакторинга. Погоня за стабильностью любой ценой ведет к технологическому устареванию.
• Удовлетворенность внутренних пользователей: Их регулярный фидбек на новые функции и изменения в интерфейсе. Важно, чтобы платформа не только работала, но и была удобным инструментом.
🎯 Итог:
Наш интуитивный фокус на стабильности был важной компонентой, но не конечной целью. Настоящая «Полярная звезда» должна быть сформулирована на языке пользы для конечного пользователя диалога.
Возможно, для нас это «Процент успешных (без технических сбоев) диалогов». Все наши действия — от исправления багов и улучшения мониторинга до рефакторинга — должны быть направлены на увеличение этого процента. А контрметрики следят, чтобы мы, повышая его, не превратили чат в надежный, но устаревший инструмент.
А вы задумывались, какая "Полярная звезда" может быть у вашей команды? 🤔
🔥4
