MiddleData Analyst > SQL и данные > Качество данных
Короткий ответ Скорее всего, таблица цен хранит несколько исторических строк на один product_id (разные периоды действия цены), и JOIN по одному только product_id без условия на дату заказа размножает строки заказа на количество версий цены (fan-out); исправление — добавить условие по дате в JOIN, выбирающее ровно одну актуальную на момент заказа запись. Как это работает подробнее Если dim_product_price_history имеет грануляцию «одна строка на период действия цены товара» (несколько строк на product_id), а JOIN сделан только по product_id без учёта valid_from/valid_to, то каждая строка fact_orders размножается на число совпавших версий цены. Пример кода Что использовать на практике На практике. Правильный JOIN должен включать условие order_date BETWEEN valid_from AND COALESCE(valid_to, 'infinity') — это гарантирует ровно одну совпавшую строку цены на каждый заказ, если периоды действия цен не пересекаются. Проверка. COUNT(*) результата JOIN должен быть равен COUNT(*) исходной fact_orders (каждому заказу соотв
data-qualityfan-out
JuniorPython Developer > Основы Python > FastAPI и Pydantic
Короткий ответ Depends указывает FastAPI вызвать переданную функцию перед основным обработчиком и передать её результат как аргумент обработчика — это базовый механизм внедрения зависимостей. Как это работает подробнее Функция-зависимость объявляется как обычная Python-функция (может иметь свои параметры — query, path, другие зависимости). FastAPI вызывает её при каждом запросе и передаёт возвращённое значение в параметр эндпоинта, помеченный Depends(функция). Пример кода Что использовать на практике Практика. Такой подход удобен для повторяющейся логики: получения текущего пользователя из токена, открытия соединения с БД, проверки прав доступа — без дублирования кода в каждом эндпоинте. Подводные камни Риск. Путают Depends(get_current_user) (вызов без скобок передаёт саму функцию, что и нужно) с ошибочным Depends(get_current_user()) (вызывает функцию один раз при определении маршрута, а не при каждом запросе).
databasedependency-injection
MiddlePython Developer > Основы Python > Функции и области видимости
Короткий ответ Код выведет [1], а затем [1, 2]. Причина — изменяемый список как значение аргумента по умолчанию: такой объект создаётся один раз и разделяется между всеми вызовами функции. Как это работает подробнее Значения аргументов по умолчанию вычисляются в момент определения функции, а не при каждом вызове. Единственный экземпляр. Когда Python выполняет строку с def, список [] создаётся один раз, и ссылка на него сохраняется как значение по умолчанию. Разделение между вызовами. Первый вызов добавляет в общий список 1, второй обращается к тому же объекту и добавляет 2 — получается [1, 2]. Накопление состояния. Такой список ведёт себя как глобальное состояние, сохраняя значения между вызовами, — это классический источник трудноуловимых багов. Другие изменяемые типы. Та же проблема возникает со словарями и множествами, поэтому их тоже избегают в значениях по умолчанию. Пример кода Что использовать на практике None как маркер. Используй None в значении по умолчанию и создавай новый список внутри функции — э
default-argumentsfunctions
MiddleData Analyst > SQL и данные > Коммуникация с бизнесом
Короткий ответ Объясню, что статистическая значимость говорит лишь о том, что эффект скорее всего не случаен, но не о том, что он достаточно велик, чтобы быть ценным для бизнеса — нужно отдельно оценить практическую значимость (денежный эффект, стоимость внедрения и поддержки) и сравнить её с затратами на изменение. Как это работает подробнее при больших выборках даже крошечный реальный эффект становится статистически значимым (p-value мал), потому что стандартная ошибка уменьшается с размером выборки. Статистическая значимость не говорит о величине эффекта и его ценности для бизнеса. Что использовать на практике Применение. перевожу 0.2 п.п. в деньги или абсолютные единицы (например, «это ~40 дополнительных заказов в месяц при текущем трафике») и сравниваю с издержками на внедрение и поддержку изменения (разработка, техдолг, усложнение интерфейса). Также проверяю доверительный интервал эффекта — если он широкий и включает близкие к нулю значения, уверенность в величине эффекта низкая. Проверка или пример. Ко
ab-testingcost-benefit-analysis
JuniorDevOps Engineer > Контейнеры и доставка > CI/CD и управление релизами
Короткий ответ В GitOps единственным источником истины для желаемого состояния окружения является Git-репозиторий с декларативными манифестами; специальный контроллер (например, ArgoCD или Flux) постоянно сверяет реальное состояние кластера с репозиторием и автоматически приводит его в соответствие. Как это работает подробнее инженер меняет YAML-манифест (например, версию образа) в Git и открывает pull request; после мерджа GitOps-контроллер, работающий внутри кластера, замечает изменение и сам применяет его через Kubernetes API — не требуется, чтобы внешняя CI-система «пушила» изменения в кластер. Пример кода Что использовать на практике На практике. такой pull-based подход снижает поверхность атаки (кластеру не нужно давать доступ внешним CI-раннерам) и даёт встроенный аудит через историю коммитов и автоматическое обнаружение дрифта — если кто-то вручную поменял ресурс через `kubectl edit`, контроллер со временем вернёт состояние к тому, что описано в Git. Пример. Ожидаемое поведение: после изменения тега н
artifactscicd-and-release-management
SeniorDevOps Engineer > Контейнеры и доставка > CI/CD и управление релизами
Короткий ответ Нет единственно верного полного решения — типичный поэтапный путь: сначала обеспечить базовую гигиену (сканирование зависимостей и образов, иммутабельные теги, ограничение, кто может пушить в registry), затем добавить генерацию SBOM при сборке, подпись артефактов (например, cosign/Sigstore) и верификацию подписи перед деплоем, и только на зрелом уровне — полную provenance-аттестацию по модели SLSA с привязкой к конкретному билд-пайплайну; выбор глубины инвестиций зависит от требований комплаенса, модели угроз и реальной стоимости инцидента компрометации цепочки поставок. Как это работает подробнее SBOM (Software Bill of Materials, например в формате CycloneDX или SPDX) описывает все зависимости, вошедшие в артефакт, что позволяет быстро определить затронутость при появлении новой уязвимости (zero-day) в популярной библиотеке. Подпись артефакта криптографически связывает образ с конкретным сборочным процессом, а verification policy (например, через admission-контроллер Kubernetes) может блокиров
artifactscicd-and-release-management
MiddleDevOps Engineer > Контейнеры и доставка > CI/CD и управление релизами
Короткий ответ Нужен один пайплайн сборки, который собирает и помечает артефакт уникальным неизменяемым тегом (например, по git-sha), публикует его в registry один раз, а дальше отдельные стадии/пайплайны деплоя последовательно разворачивают именно этот тег в dev, затем staging, затем prod, не пересобирая код и подставляя только конфигурацию, специфичную для окружения. Как это работает подробнее стадия `build` производит один артефакт и его метаданные (например, файл `image-tag.txt` с конкретным digest/тегом), который сохраняется как pipeline-артефакт или просто публикуется в registry с уникальным тегом. Стадии деплоя в разные окружения читают этот же тег и применяют его с окружение-специфичными values/ConfigMap, не трогая сам образ. Пример кода Что использовать на практике На практике. такой подход даёт гарантию, что в prod работает именно то, что было протестировано на staging, упрощает откат (можно вернуть предыдущий известный тег) и ускоряет повторные деплои. Обычно между стадиями ставят gate — автоматиче
artifactsbuild-once-deploy-many
SeniorData Analyst > SQL и данные > Продуктовые и бизнес-метрики
Короткий ответ Система метрик строится сверху вниз (от гипотезы о ценности продукта к North Star Metric, затем к 3-5 input-метрикам, на которые команды реально влияют, и к guardrail-метрикам, защищающим от побочного вреда), но единственно верной структуры не существует — выбор всегда компромисс между простотой, измеримостью и полнотой отражения ценности. Как это работает подробнее сначала формулируется гипотеза о том, в какой момент пользователь получает основную ценность продукта ("aha-moment"), затем ищется метрика, которая одновременно растёт вместе с этой ценностью и с бизнес-результатом; под NSM выстраивается дерево input-метрик через декомпозицию (например, NSM = активные команды × частота ключевых действий), и для каждого input-а назначается ответственная команда. Для нового B2B-инструмента совместной работы: гипотеза ценности — "команды, которые создают и совместно редактируют документы, остаются дольше"; NSM = число команд с ≥3 активными участниками в неделю; input-метрики = activation rate новых ком
guardrailsmetric-tree
MiddleDevOps Engineer > Контейнеры и доставка > CI/CD и управление релизами
Короткий ответ Каждый собранный образ должен получать неизменяемый уникальный тег, построенный на git-коммите (например, `sha-` или семантическую версию для релизных тегов), и в манифестах деплоя использовать именно этот тег (а ещё надёжнее — immutable digest `@sha256:...`), не полагаясь на плавающие теги вроде `latest`, `dev`, `stable`. Как это работает подробнее неизменяемый тег однозначно привязан к конкретному содержимому образа — его нельзя перезаписать, не изменив имя. Digest (sha256-хэш содержимого манифеста образа) даёт ещё более сильную гарантию, чем тег: даже если кто-то случайно перепушит тег с тем же именем (что multiple registries позволяют запретить через immutability settings), digest всё равно укажет на исходное содержимое. Пример кода Что использовать на практике На практике. плавающие теги (`dev`, `latest`, `stable`) удобны для человекочитаемой навигации, но не должны использоваться как единственный способ деплоя в GitOps-манифестах, иначе невозможно точно сказать, какая версия сейчас работа
artifactscicd-and-release-management
MiddlePython Developer > Основы Python > Проектирование API
Короткий ответ Offset-пагинация (LIMIT/OFFSET) проста, но даёт сдвиги и дубликаты/пропуски при параллельных вставках/удалениях и деградирует по производительности на больших смещениях; cursor-based пагинация (по последнему увиденному значению ключа) устойчива к изменениям данных между запросами страниц и быстрее на больших датасетах, но не позволяет прыгать на произвольную страницу по номеру. Как это работает подробнее offset-пагинация просит БД пропустить N строк и вернуть следующие M — при больших N база всё равно сканирует/сортирует пропущенные строки, что линейно растёт по стоимости. Cursor-пагинация использует значение (обычно ID или комбинацию полей сортировки) последней полученной записи как отправную точку для следующего запроса (WHERE id > :last_id ORDER BY id LIMIT :limit), что позволяет БД использовать индекс для быстрого поиска стартовой точки без сканирования пропущенных строк. Пример кода Что использовать на практике Рекомендация. если пользователю нужно показать номера страниц и дать переход "н
cursor-paginationoffset-pagination