Последние посты

Советы разработчикам (python и не только)
31 мая, 18:13изменён
Юзкейсы, сценарии и интеракторыКогда мы пишем наш код (программу, сервис, библиотеку), мы так или иначе анализируем зачем она нужна. У пользователей и заказчика продукта есть цели. Бизнес хочет получить прибыль, покупатель - получить товар, пользователь техподдержки - не показаться начальнику глупым, чтобы его не уволили. Есть цели более глобальные, такие как достижение благополучия, есть более конкретные подцели, как доставка товара на конкретный адрес.Зачастую с системой взаимодействуют не только люди, поэтому часто используют более общий термин — актор.Анализируя цели и потребности всех участников взаимодействия, мы приходим к формулированию требований, одной из форм которых являются use cases, которые и описывают взаимодействие некоторого актора с системой ради удовлетворения его целей. Каждый юзкейс - это текстовый документ, но они могут дополняться диаграммами. Юзкейсы могут
Советы разработчикам (python и не только)
17 февр., 09:25
Меня позвали поговорить о разном: о проектах, опыте, программировании в целом.https://www.youtube.com/watch?v=B4XrghSsUhQYouTubeAdaptix vs Pydantic: или почему код на Python может работать быстро? / Python Mentor Podcast #3*** 💡Ламповое комьюнити питонистов в Telegram: https://t.me/pymentor ✒️ Собесы, интервью, подкасты: https://www.youtube.com/@pymentor_by/playlists 📡 Записаться на тестовый (мок) собес: https://t.ly/lXoVH ✉️ Связь с автором канала - python.mentor.by@gmail.com…
Советы разработчикам (python и не только)
11 янв., 11:54
SQLAlchemy и ORMSQLAlchemy в python предоставляет два набора API:1. Возможность конструировать и выполнять запросы в БД 2. Получать и сохранять сущностиПервый набор api (Core функциональность) - это в первую очередь объекты запросов select, insert, update и других, а также метод execute, который есть у объекта Сonnection (можно использовать Session, но о нем ниже). Часто при этом используются объекты Table для описания структуры БД.Кроме этого, sqlalchemy можно использовать как ORM. Это означает, что вы создаете классы, описывающие ваши сущности, а затем все операции с БД делаете только через них: вы загружаете сущности, сохраняете сущности, удаляете сущности (см. пост про стейт приложения и БД). При этом Connection вам уже недостаточно, вам требуется Session.В чем ключевые отличия ORM подхода от Core?• Для загрузки сущностей используется session.get для получения по
Советы разработчикам (python и не только)
4 нояб. 2025 г., 12:30
Asyncio и колбэкиВ прошлом посте мы рассмотрели как asyncio взаимодействует с генераторами, но на более низком уровне он взаимодействует с колбэками, а генераторы и корутины - вспомогательные возможности для более удобного написания кода.Базовая функциональность лупа заключается в том, что он умеет вызывать в цикле синхронные функции. Пока один колбэк не отработает, луп не перейдет к другому. Такие функции можно добавить через вызов loop.call_soon (или loop.call_soon_threadsafe, если мы хотим это сделать из другого потока). Дополнительно, у него есть некоторые другие функции вроде задания задержки вызова функции.Следующий важный объект - Future. Его задача достаточно простая - хранить некоторый результат и вызывать колбэк при его установке. И все ещё это обычная синхронная функция, но уже вызывающаяся не планировщиком лупа, а напрямую, когда кто-то делает set_resultОднако взаимод
Советы разработчикам (python и не только)
27 сент. 2025 г., 17:51изменён
Стейт при работе с базами данныхПодходы работы с БД можно разделить на две группы:• Ориентированные на состояние в памяти (ActiveRecord, Data Mapper, UoW) • Ориентированные на действия с состоянием в БД (DAO)Если ты ориентирован на состояние в памяти, то фактически твоё приложение имеет вид1. Загрузил состояние сущностей 2. Выполнил необходимые операции по его изменению 3. Сохранил состояниеТакой подход позволяет тестировать логику изменения без базы данных, а так же унифицировать взаимодействие с БД, тем самым снижая сложность кода. Однако появляются и ограничения:• Если кроме указанных операций что-то изменить напрямую в БД, то загруженный стейт перестанет соответствовать состоянию в БД. Любые операции с ним могут привести к некорректному результату. Чтобы этого не произошло, не стоит выполнять insert/update/delete запросы кроме как при сохранении состояния после изменения.
Советы разработчикам (python и не только)
7 авг. 2025 г., 14:01
Asyncio и цикл событийЧтобы понять, как рабоатет asyncio, давайте рассмотрим, как в Python работают функции.Мы можем вызвать функцию, она выполнится. Просто интерпретатор берет её код и выполняет целиком. Если же мы берём функцию-генератор и просто вызываем, ничего не будет происходить. Тебе надо по ней пробежаться циклом или самому вызывая next. Когда мы вызываем next, код функции доходит до следующего yield и останавливается.Представим, что у нас есть основной части программы цикл, который крутит этот генератор.def foo(): yield 1 yield 2for _ in foo(): passЕсли между yield вызывается обычная функция, то она выполняется как обычно, и не важно, что это происходит внутри генератора. А что, если наш генератор внутри себя вызывает другой генератор через yield from?def foo(): yield 1 yield 2
Советы разработчикам (python и не только)
2 апр. 2025 г., 15:27изменён
Anti corruption layerЧасто в наших приложениях мы обращаемся к каким-то внешним системам. Иногда мы просто обращаемся к ним, иногда ждем обратных вызовов. Это может быть платежная система, сервис уведомлений, инвентаризации или что-то ещё.Ключевое в таких интеграциях то, что такие системы имеют свой жизненный цикл, свой контекст и часто их устройство слабо похоже на то, что нам надо от них, однако интеграция с ними может быть жизненно необходима для нашего приложения.Для того, чтобы сделать наше приложение более устойчивым к изменениям внешнего API и одновременно сохранить нашу логику чистой, мы выделяем отдельный компонент - Anti Corruption Layer. Его задача - скрыть за собой детали взаимодействия с этой системой, предоставив нашей бизнес логике понятное ей API.Структура с использованием ACL может состоять из таких частей: • Какая-то часть нашей бизнес-логики использует


Советы разработчикам (python и не только)
14 мар. 2025 г., 08:53
СловариСловари есть во многих языках программирования и предназначены для поиска и хранения значений, связанных с некоторыми ключами. В простом случае словарь можно представить как список пар ключ-значение, но ключи уникальны.Основная задача словаря - обеспечивать доступ по ключу, поэтому мы хотим, чтобы он делал это эффективно. Если хранить пары как обычный неупорядоченный список, для поиска придется перебирать его каждый раз, но можно сделать быстрее.Одна из возможных реализаций словаря - использование сбалансированных деревьев поиска (обычно красно-черных). Принцип работы заключается в том, что для каждого узла дерева все что в правой ветке - больше него, а всё что в левой - меньше. Если ветки не сильно разной длины, мы можем достаточно быстро так найти нужный элемент. Единственное, что требуется от ключей - возможность их сравнивать на <,> и =. Результат сравнения не должен
Советы разработчикам (python и не только)
8 мар. 2025 г., 11:49изменён
Dependency Inversion PrincipleПринцип инверсии зависимостей (DIP) часто путают с техникой внедрения зависимостей (DI), но это разные вещи, служащие разным целям. Начнем с самой инверсии.Представим ситуацию: у нас есть компонент А и ему для работы нужен компонент D. Например, для обработки данных нам надо их загрузить из БД. Это прямая зависимость: компонент А знает о компоненте D, а компонент D не знает о компоненте А. Под знанием я имею в виду использование в коде типов, импортов, да и в целом проектирование одного куска кода исходя из того, как устроен второй.Инверсия этой зависимости получится когда компонент А перестанет знать о компоненте D, а вместо этого компонент D станет знать о компоненте А. То есть обработка данных не знает о том, как они загружаются, но код загрузки данных может знать, что их будут обрабатывать. Держим в голове, что D все ещё должен использоваться


Советы разработчикам (python и не только)
20 февр. 2025 г., 09:34
float и DecimalВас никогда не удивляло, что 0.1 + 0.2 != 0.3? Почему float считает с погрешностями, и всем норм?Дело в том, что 0.1 выглядит как0 0111111101 11001100110011001100110011001100110011001100110011010.Где: • 0 обозначает знак + (и 1 обозначает -) • 0111111101 обозначает exponent, равную 0^10 + 2^9 + 2^8 + 2^7 + 2^6 + итд = 1019. Вычтем 1023 (размерность double) и получим итоговое значение: 1019 - 1023 = 4 • 11001100110011001100110011001100110011001100110011010 обозначет "significand" или "мантису", которая равна: 2^-exp + 2^-exp-1 + 2^-exp-2 + итд ~= 0.1Вот так мы можем примерно представить 0.1 в виде float. Примерно – потому что все вычисления идут с погрешностью. Мы можем проверить данное утверждение, добавив погрешность вручную:>>> assert 0.1 + 2.220446049250313e-18 == 0.1Значение внешне не изменилось при добавлении погрешности. Посмотрим на
Советы разработчикам (python и не только)
3 янв. 2025 г., 16:03изменён
Паттерны работы с базами данныхВ большинстве проектов мы храним какие-то данные. Для этого используются разные виды баз данных: реляционные, nosql или даже специализированные HTTP API. Такие хранилища имеют специфическое API, которое мы обычно хотим скрыть от основного кода за некоторой абстракцией. Вот стандартные варианты, описанные, в частности, Мартином Фаулером.Первая группа паттернов работы с БД - отделяющие реализацию операций с хранилищем от данных. Благодаря такому разделению, мы можем построить несколько реализаций шлюза, возвращающих однотипные структуры (например, для заглушек на время тестирования или использования нескольких источников данных). Обратите внимание, что в паттернах этой группы мы можем полностью скрыть детали организации хранилища.DAO - наиболее простой вариант, он представляет собой достаточно тупой класс, который просто выполняет операции с хранилищем


Советы разработчикам (python и не только)
27 нояб. 2024 г., 19:32
Data Transfer ObjectКогда мы общаемся с удаленным кодом (посылаем запросы, сообщения), пересылаемые данные в коде зачастую удобнее передавать совместно и представлять не в виде отдельных параметров методов, а в виде некоторой структуры. Она называется DTO - Data Transfer Object (объект передачи данных).DTO - любой объект/структура данных без своей логики, пригодная для сериализации для передачи по сети. При этом не обговаривается как именно она будет сериализована - она может содержать специальные методы, или этим может заниматься отдельный код (на основе интроспекции, макросов или как угодно).DTO - это, в первую очередь, назначение объекта. Это данные, которые надо передать. Могут иметься в виду входящие, так и исходящие данные.1. Для существования DTO не требуется наличие каких-либо доменных моделей, это любые данные. Они могут собираться из других DTO, нескольких
Советы разработчикам (python и не только)
14 окт. 2024 г., 07:37изменён
Полиморфизм при наследовании и LSP.Когда мы строим иерархию объектов, мы часто делаем одноименные методы с разным поведением. Если в родительском классе такой метод отсутствует, то мы в целом вольны в наследниках делать что захотим.Если же родительский класс содержит такой метод, то у нас есть следующие варианты:1. Реализация в дочернем классе полностью сохраняет внешнее поведение метода (параметры, результат, побочные эффекты), но отличается реализацией и как следствие нефункциональными характеристиками (например, производительностью). В этом случае классы полностью взаимозаменяемы. 2. Реализация в дочернем классе полностью сохраняет поведение родительского класса, но делает дополнительную работу или меняет поля, отсутствующие в родительском классе. Мы все также можем использовать дочерний класс там, где ожидается родительский, но в других частях программы мы получаем
Советы разработчикам (python и не только)
20 сент. 2024 г., 11:16изменён
Аутентификация и IdentityProviderДля реализации идентификации и аутентификации мы неизбежно используем данные, не нужные основной логике приложения, а логика может быть достаточно сложной сама по себе:• Для событий телеграм идентификация происходит на основе данных из события. Аутентификация пользователя не производится - мы только проверяем безопасность соединения с сервером • Для бэкенда веб приложения мы часто используем сессии. В этом случае мы достаем их из cookie и дальше проверяем в какой-либо базе данных, откуда и достаем идентификатор пользователя, соответствующего сессии. • Для API в микросервисной среде мы можем использовать JWT-токены, содержащие айди пользователя, которые проверяются на основе подписи. • В некоторых сервисах мы можем полагаться на пользовательские TLS-сертификаты, заверенные сертифицирующем сервисом • Проверка токена или сертификата может делаться как в
Советы разработчикам (python и не только)
17 июн. 2024 г., 06:50
Аутентификация и авторизацияНаши приложения выполняют разные сценарии и для некоторых из них может быть важно, что за пользователь перед нами. То есть, для целей бизнес-логики может быть необходимо получить некоторые уникальные данные пользователя, которые позволят его отличить от других - это идентификация. Реализуется она различным способом: иногда мы можем явно спросить у пользователя, кто он, иногда мы получаем информацию из сетевых пакетов или системы. Идентификационные данные дальше могут использоваться по-разному: их можно записать в лог, использовать как ссылку на владельца при создании объектов в системе или в различных проверках внутри нашей логики.Идентификация должна выполняться безопасно: иногда пользователь может попытаться выдать себя за другого. Процесс проверки, что пользователь не обманывает нас в том, кто он - аутентификация. Она не всегда актуальна: если мы
Советы разработчикам (python и не только)
30 мая 2024 г., 12:36изменён
У ребят из Podlodka Python Crew стартует новый сезон онлайн-конференции, тема — инфраструктура. Всё проходит онлайн, с 3 по 7 июня.Я буду выступать там с докладом про Dependency Injection и dishka непосредственно.Все доклады записываются, так что смотреть их день в день необязательно.Что будет • Мой доклад про DI • Погружение в трейсинг: чем он полезен, как работает и как его внедрить. • Поиск уязвимостей: практические задания с разбором • Рассказ про неочевидные кейсы оптимизации. • Обучение эффективному мониторингу: типы метрик, как их собирать и экспортировать. И ещё много всего.Конференция платная, но специально для подписчиков промокод INFRA_17 на скидку 1000рЗапись выступления доступна тут: http://www.youtube.com/watch?v=gWOBaZ3I4gc
Советы разработчикам (python и не только)
12 мая 2024 г., 09:03изменён
Unit of workПаттерн Unit of work (единица работы) предназначен для того, чтобы следить за изменениями объектов и потом координировано их сохранять в базу данных.Это позволяет:• Ограничить время жизни транзакции • Не выполнять обращение к БД сразу при выполнении изменений, а значит попытаться сделать это более эффективно • Более удобно следить за изменениями в случае сложной иерархии или большого количества типов моделей.Принцип использования Unit of Work состоит из двух этапов:1. Сначала мы регистрируем в нем, что с нашими моделями были изменения (register_new, register_dirty, register_deleted). 2. Затем в какой-то момент сохраняем все эти изменения в БД (commit)Изменения могут регистрировать как сами модели, так и прикладной код, использующий их. Таким образом, каждый раз, когда мы что-то делаем с моделями (добавляем, удаляем, изменяем), мы не отправляем сразу запрос в БД,
Советы разработчикам (python и не только)
3 апр. 2024 г., 09:35изменён
Dishka - IoC-контейнер для PythonКогда мы следуем подходу Dependency Injection, а особенно - слоистой архитектуре, у нас образуется отдельная группа функций и классов, выполняющих только одну задачу - создание других объектов. Такой код лучше держать поближе к main, так как он связывает воедино разные части приложения и связан с конфигурацией запуска.В сложном приложении такой компонент может содержать большое количество функций, контролировать как создание, так и корректную очистку объектов и, что самое главное, их взаимосвязь. Для упрощения работы с такими фабриками придумали отдельный тип библиотек - IoC-контейнеры (DI-фреймворки).В Python меня долго не устраивали существующие контейнеры и я решил сделать свой:Хочу представить вам Dishka 1.0Цель этого проекта - предоставить простой и удобный IoC-контейнер, который сможет забрать всю работу с зависимостями. Мне кажется, на


Советы разработчикам (python и не только)
22 мар. 2024 г., 18:08
Абстрактные классы и интерфейсыЕсли рассуждать, не привязываясь к языку программирования, то:Абстрактный класс - это заготовка для класса. В нем часто есть методы с реализацией и методы, помеченные как абстрактные. Экземпляры такого класса напрямую создавать нельзя. Нужно отнаследоваться от него и заполнить пропущенные методы.Абстрактный класс может содержать данные, обычные методы. Его отличает именно наличие абстрактных методов. В некоторых языках - это методы без тела (C++, Java), в некоторых (Python) - методы со специальной пометкой. Чтобы наследник класса перестал быть абстрактным, надо реализовать в нем все такие методы.Интерфейс же - это требования к тому, что должен уметь объект. Это набор сигнатур операций. Как правило, речь о наборе названий методов, их параметрах и типе результата, но иногда речь и про доступ к атрибутам. В общем случае, интерфейс может не
Советы разработчикам (python и не только)
9 янв. 2024 г., 23:55
Виртуальные окружения PythonВо многих случаях при разработке приложений на Python нам требуются сторонние библиотеки. Однако, если мы будем их устанавливать в глобальное окружение, мы в какой-то момент столкнемся с конфликтами между разными проектами, нам будет сложнее производить очистку такого окружения. А в некоторых ситуациях мы можем даже сломать системные приложения.Чтобы избежать таких проблем, рекомендуется практически всегда использовать виртуальные окружения. Это специальная папка, куда устанавливаются библиотеки и которых может быть больше одной на вашем компьютере. В python 3 есть встроенное средства для управления ими - пакет venv, но есть и сторонние популярные решения такие как virtualenv, poetry и многие другие.Для того чтобы создать новое виртуальное окружение, выполните команду с указанием нужного вам питона:python -m venv имя_папкиПосле этого в каталоге
