Воспроизводимая методика диагностики developer experience (DX) любого Python-SDK, работающего поверх HTTP API. Цель методики — не бинарная проверка, а поиск слабых мест пользовательского опыта и приоритезация улучшений.
Методика универсальна: она не привязана к конкретным классам, файлам или методам. Все критерии формулируются через роли, контракты и поведение, а не через имена в коде.
- Удобство интеграции. Путь от «установил пакет» до «сделал первый успешный запрос».
- Удобство повседневной разработки. Скорость поиска нужного метода, предсказуемость поведения, стоимость отладки, стоимость тестирования своего кода поверх SDK.
- Удобство сопровождения. Поведение при апгрейде, при смене API upstream, при смене окружения, при сбоях сети.
Методика не оценивает:
- производительность (latency, throughput, память);
- архитектурную чистоту ради чистоты;
- полноту функциональности upstream API (это отдельная метрика «coverage», входящая только частично).
Цели:
- Получить количественную оценку
Score ∈ [0, 100], сопоставимую между релизами и между разными SDK. - Локализовать слабые места до уровня поведения/контракта (без привязки к конкретному файлу).
- Выдать приоритезированный backlog улучшений (через индекс
Pain, см. §6).
Ограничения:
- Методика рассчитана на SDK-обёртки поверх HTTP/REST API. Для gRPC, WebSocket или низкоуровневых библиотек часть критериев неприменима и отключается явно.
- Минимальная оценка — один оценщик за ~1 рабочий день. Эталонная — два независимых оценщика, кросс-проверка.
- Некоторые критерии требуют участия пользователей (персон-сессии); если доступа к реальным пользователям нет, применяется имитационный режим (оценщик играет роль персоны).
Допущения:
- SDK имеет публичный репозиторий или доступ к исходникам.
- SDK распространяется через PyPI/подобный индекс, устанавливается одним шагом.
- Есть хотя бы минимальная документация (README, docstring).
Каждый подкритерий оценивается с позиции трёх персон. Итоговый балл подпункта = минимум из трёх оценок (слабое звено определяет DX).
- P1. Интегратор-новичок. Впервые использует SDK. Опирается на README, quickstart и IDE-подсказки. Читает исходный код только в крайнем случае.
- P2. Опытный разработчик. Пишет продакшен-код, использует
mypy, отлаживает инциденты, пишет свои тесты поверх SDK. - P3. Сопровождающий. Обновляет версию SDK в своём проекте, следит за релизами, поддерживает обратную совместимость собственного кода, собирает баг-репорты.
Единый набор методов — в каждом критерии явно указано, какие применяются.
| Код | Метод | Описание |
|---|---|---|
| AC | Auditing Code (аудит кода) | Ручное чтение публичного API, не углубляясь в реализацию. Роль оценщика — «умный читатель», а не автор |
| SA | Static Analysis | Применение статических анализаторов: типов, стиля, docstring, мёртвого кода, security-lint |
| FI | Fault Injection | Контролируемая подстановка ошибок (5xx, 401, timeout, битый JSON) через моки и прокси |
| TT | Timed Task | Задача на время: замеряется, за сколько персона доходит до результата |
| TAL | Think-Aloud Lab | Пользовательская сессия с протоколом «думаю вслух»: фиксация моментов застревания |
| HE | Heuristic Evaluation | Эвристический анализ по 10 DX-эвристикам (см. §5.5) |
| CB | Comparative Benchmark | Сравнение конкретного поведения с эталонными SDK (Stripe, Azure, Google Cloud, boto3, OpenAI) |
| DA | Document Audit | Сверка публичной документации с фактическим поведением SDK |
| LA | Log Analysis | Анализ логов SDK: что пишется, на каких уровнях, нет ли утечек секретов |
| AM | Automated Metric | Любой машинно-извлекаемый показатель: покрытие тестами, количество публичных символов с docstring, число TODO/FIXME и т. д. |
Каждый подкритерий должен иметь ≥1 метод из множества {SA, FI, DA, AM, CB} — то есть хотя бы один источник, не зависящий от субъективного суждения. Ручные методы (AC, TT, TAL, HE) применяются в дополнение, но не как единственный источник.
- ruff — стилистические нарушения, базовые антипаттерны, dead code, часть
flake8-правил. - mypy в режиме
--strict— полнота типизации,Any-утечки, расхождения аннотаций и runtime. - pyright (альтернативно) — более быстрый и строгий статический анализатор типов.
- bandit — security-lint (hardcoded secrets, небезопасные паттерны).
- vulture — поиск мёртвого кода: неиспользуемых импортов, функций, классов.
- radon / xenon — цикломатическая сложность публичных методов.
- interrogate — покрытие публичного API docstring'ами.
- pydocstyle — формат docstring.
- pytest — база для контрактных, интеграционных, error-mapping тестов.
- respx / httpx-mock — мок HTTP-слоя для
httpx-клиентов. - vcrpy / pytest-recording — запись и воспроизведение реальных HTTP-сессий для регрессии.
- pytest-httpserver — поднятие тестового HTTP-сервера, способного имитировать 4xx/5xx/medleys.
- toxiproxy / mitmproxy — имитация сетевых аномалий: jitter, обрывы, rate-limit.
- hypothesis — property-based тесты для граничных условий сериализации и мапперов.
- freezegun — фиксация времени для проверки retry-after и backoff.
- vale — прозовый linter для стиля документации и терминологии.
- markdownlint — качество разметки Markdown.
- sphinx-build -W — сборка reference без предупреждений.
- link-checker (например,
lychee) — проверка мёртвых ссылок. - Diátaxis-матрица — ручная категоризация существующих материалов (см. §9.15).
- Time-to-First-Call (TTFC) — метрика в секундах от
pip installдо первого успешного реального запроса, замеряется секундомером. - Task Success Rate (TSR) — доля пользователей, решивших тестовую задачу без помощи.
- System Usability Scale (SUS) в варианте DevSUS — анкета из 10 вопросов, адаптированная для SDK. Итог от 0 до 100, эталон ≥80.
- Think-aloud protocol — пользователь комментирует ход решения; оценщик фиксирует точки застревания.
- Diary study (для P3) — сбор заметок сопровождающего за 1–2 спринта использования.
Адаптированный чек-лист Нильсена для SDK:
- Видимость состояния. Пользователь понимает, где сейчас происходит сетевой вызов, а где нет.
- Соответствие доменному языку. Имена методов отражают операции предметной области, не HTTP.
- Свобода и контроль. Есть per-operation overrides и «побег» в низкоуровневые примитивы при необходимости.
- Консистентность и стандарты. SDK следует Python-конвенциям (snake_case, PEP 8) и внутренним конвенциям по всей поверхности.
- Предупреждение ошибок. Некорректный ввод ловится до сети (fail-fast).
- Узнавание, а не вспоминание. IDE-autocomplete предоставляет всё необходимое без обращения к документации.
- Гибкость и эффективность. Новичок проходит happy-path за минуты; опытный пользователь получает доступ к тонкой настройке.
- Минимализм. Публичный API содержит только то, что нужно; остальное скрыто.
- Язык ошибок. Сообщения помогают диагностировать и действовать, не просто констатируют факт.
- Справка и документация. Покрыты все четыре режима Diátaxis: tutorials, how-to, reference, explanations.
Сравнение поведения проводится с эталонными Python-SDK:
- Stripe (
stripe-python) — идемпотентность, auto-pagination, error-mapping. - Azure SDK for Python — клиент-конструктор, long-running operations,
ItemPaged. - Google Cloud Python — ADC, прозрачная пагинация.
- boto3 — конфигурация, ретраи, сессии.
- OpenAI Python SDK — async/sync parity, потоковые ответы.
Для каждого поведения методика требует сформулировать ответ: «в эталоне реализовано через X, в оцениваемом SDK реализовано через Y; разница в DX такая-то».
| Уровень | Балл | Признак |
|---|---|---|
| Отсутствует | 0% | Требование не выполнено; дефект виден в первые минуты работы |
| Частичное | 25% | Выполнено в отдельных местах, в остальных нарушено |
| Базовое | 50% | Выполнено для большинства случаев, есть системные исключения |
| Хорошее | 75% | Выполнено везде, редкие мелкие отклонения |
| Эталонное | 100% | Выполнено, нет признаков слабости, сопоставимо с лучшими SDK |
Промежуточные значения допустимы с обоснованием.
Score = Σ ( weight_criterion_i × Σ ( weight_subcriterion_ij × grade_ij ) )
где grade_ij ∈ [0, 1], Σ weight_criterion = 100%, внутри каждого критерия Σ weight_subcriterion = weight_criterion.
- ≥ 90% — эталонный DX, сопоставимо с лучшими SDK индустрии.
- 75–89% — рабочий инструмент, заметные шероховатости в 1–2 критериях.
- 60–74% — DX-долг, нужен плановый рефакторинг.
- < 60% — требуется архитектурный пересмотр до широкой публикации.
Для каждого подкритерия с grade < 0.75:
Pain = weight_subcriterion × (1 - grade) × persona_multiplier × cadence_multiplier
где:
persona_multiplier = 1.5, если просадка затрагивает персону P1 (новичок), иначе 1.0 — новичок уходит из SDK быстрее всего;cadence_multiplier = 1.3, если слабость проявляется в повседневном сценарии (пишется/читается в каждой второй строке кода пользователя), 1.0 в остальных случаях.
Backlog сортируется по убыванию Pain. Верхний квартиль — цель ближайшего спринта.
Сумма весов = 100%.
| # | Критерий | Вес |
|---|---|---|
| 1 | Онбординг и Time-to-First-Call | 10% |
| 2 | Discoverability публичного API | 8% |
| 3 | Именование и согласованность | 4% |
| 4 | Типизация и IDE-friendliness | 10% |
| 5 | Моделирование данных и возвращаемые типы | 6% |
| 6 | Обработка ошибок и actionability | 8% |
| 7 | Безопасность использования | 6% |
| 8 | Надёжность под нестабильной сетью | 7% |
| 9 | Идемпотентность write-операций | 3% |
| 10 | Пагинация и работа с коллекциями | 4% |
| 11 | Per-operation overrides | 3% |
| 12 | Async/sync parity | 3% |
| 13 | Конфигурация и fail-fast | 4% |
| 14 | Покрытие контракта API | 4% |
| 15 | Документация (Diátaxis) | 7% |
| 16 | Тестируемость пользовательским кодом | 5% |
| 17 | Observability и логирование | 3% |
| 18 | Совместимость и deprecation policy | 5% |
Ниже — развёрнутое описание каждого критерия.
Цель. Измерить путь от «узнал про SDK» до «увидел первый результат».
Ключевая метрика. TTFC (минуты).
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 1.1 | Установка одной командой без системных зависимостей | 1% | TT, DA | pip install в чистом venv, замер времени и ошибок |
| 1.2 | Quickstart в README воспроизводим copy-paste | 2% | TT, DA | Чистый venv, прогон примеров из README, подсчёт ручных правок |
| 1.3 | Первый успешный вызов требует ≤5 строк кода | 2% | AC, TT | Подсчёт LoC для канонического сценария |
| 1.4 | Переменные окружения документированы, priority-resolution описан | 1% | DA | Сверка документации с поведением при конфликте env vs .env |
| 1.5 | Fail-fast на некорректной конфигурации | 2% | FI | Удаление обязательных полей, проверка: ошибка до сети, понятный класс, без секретов |
| 1.6 | Canonical TTFC ≤ 15 минут для P1 | 2% | TT, TAL | Видеозапись сессии новичка, секундомер |
Процедура.
- Поднять чистый venv, зафиксировать точное время.
- Выполнить
pip install <sdk>; засечь время установки и вывод предупреждений. - Скопировать quickstart в файл, запустить. Любая ручная правка уменьшает балл 1.2 на 25%.
- Замерить TTFC до первого реального сетевого ответа.
- Намеренно убрать одно обязательное поле конфига, поймать исключение, оценить качество сообщения.
Симптомы слабых мест.
- README ведёт через «полный пример» раньше «минимального».
- Обязательные поля требуют создания промежуточных объектов.
- Ошибка конфигурации маскируется под сетевое исключение.
pip installтребует системных пакетов без предупреждения.
Шаблон фиксации: «Канонический сценарий — N строк, TTFC — M минут, ручных правок — K, первое сообщение ошибки конфигурации — <цитата>».
Цель. Измерить, сколько усилий нужно, чтобы найти правильный метод без чтения исходников.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 2.1 | Единая точка входа (фасад) | 2% | AC, HE-2, CB | Сравнение с Stripe/Azure: все сценарии от одного корня |
| 2.2 | Фабричные методы по предметным областям | 2% | AC | IDE autocomplete на корневом клиенте показывает все домены |
| 2.3 | Один очевидный путь для каждой операции | 2% | AC, DA | Поиск дублей по документации и по публичным именам |
| 2.4 | Навигация по структуре пакета предсказуема | 1% | AC, HE-4 | Соответствие имен подпакетов разделам API |
| 2.5 | Имена методов отражают бизнес-действия | 1% | AC, HE-2 | Отсутствие post_*/do_* стилей |
Процедура.
- Дать P1 задачу сформулированную на языке предметной области (напр. «отправь сообщение X пользователю Y»). Замерить время до правильного метода.
- Открыть корневой объект SDK в IDE, проверить наличие всех доменов в autocomplete.
- Собрать список публичных методов и проверить дубли: две точки доступа к одним данным — минус балл 2.3.
Симптомы.
- Для одного действия есть два эквивалентных пути без пометки deprecation.
- Имена подпакетов не соответствуют привычным названиям операций.
find . -name "utils*.py"находит файлы с существенной бизнес-логикой.
Цель. Согласованный стиль именования = меньше времени на изучение.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 3.1 | Следование PEP 8 и Python-конвенциям | 1% | SA | ruff, pep8-naming |
| 3.2 | Согласованные префиксы операций (get_, list_, create_, ...) |
1% | AC, AM | Скрипт, группирующий публичные методы по префиксу |
| 3.3 | Идентификаторы доменно-специфичные (без resource_id, entity_id) |
1% | AM | grep по абстрактным именам в публичных сигнатурах |
| 3.4 | Одинаковый порядок параметров в похожих методах | 1% | AC | Визуальное сравнение сигнатур одного семейства |
Процедура. Прогнать ruff и pep8-naming; выгрузить список публичных методов в CSV с колонками prefix, nouns, params; визуально проанализировать.
Цель. Защитить пользователя на уровне статики; дать максимум подсказок в IDE.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 4.1 | Публичный API полностью типизирован | 3% | SA | mypy --strict, pyright --strict |
| 4.2 | Нет Any/dict[str, Any]/object в публичных сигнатурах |
2% | SA, AM | grep по сигнатурам + mypy-репорт |
| 4.3 | Runtime-тип совпадает с аннотацией | 1% | AC, FI | Сравнение declared vs actual на коллекциях (итераторы, lazy) |
| 4.4 | Закрытые наборы значений выражены enum'ами | 2% | AC, DA | Сверка с OpenAPI: поля с enum должны быть типизированы |
| 4.5 | IDE показывает типы аргументов, return, исключений | 2% | HE-6, AC | Открыть 10 случайных публичных методов в IDE |
Процедура. CI-прогон mypy --strict и pyright --strict с выгрузкой списка ошибок; grep ": Any", -> Any, -> dict; выборка из 10 методов — ручная проверка IDE hover.
Инструменты ранжирования эффекта: подкритерий 4.1 — это exit_code от mypy; 4.2 — количество попаданий grep делённое на общее число публичных сигнатур; 4.5 — оценочно, через HE.
Цель. Пользователь работает с доменными объектами, а не с «сырыми» структурами.
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 5.1 | Публичные методы возвращают типизированные модели, не словари | 2% | AC, SA |
| 5.2 | Поля моделей имеют конкретные имена предметной области | 1% | AC |
| 5.3 | required и Optional выражены явно и совпадают со спекой |
1% | DA |
| 5.4 | Единая сериализация (to_dict/model_dump) для всех публичных моделей |
1% | AC, AM |
| 5.5 | Транспортные поля скрыты от публичных моделей | 1% | AC |
Процедура. Выборка 20 публичных моделей; для каждой: сериализовать в JSON стандартной функцией, проверить отсутствие служебных полей, сверить nullability со спецификацией.
Цель. Ошибка помогает диагностировать и действовать.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 6.1 | Иерархия доменных исключений покрывает значимые HTTP-статусы | 2% | FI | pytest-httpserver с последовательностью 400/401/403/404/409/422/429/5xx |
| 6.2 | Семантически различные ошибки не связаны наследованием | 1% | AC | Анализ графа исключений |
| 6.3 | Сообщения ошибок содержат operation, status, request-id, attempt | 2% | FI, AC | Захват исключения, проверка атрибутов |
| 6.4 | Сообщения actionable (что случилось + что делать) | 1% | HE-9 | Выборка 20 ошибок, оценка по чеклисту actionability |
| 6.5 | Parse-ошибки и transport-ошибки различимы по типу | 1% | FI | Подача битого JSON vs обрыва сети |
| 6.6 | Probe-методы возвращают bool, не бросают |
1% | FI, AC | Проверка поведения exists-style на 404 |
Процедура. Построить матрицу (статус × тип сбоя) → ожидаемый класс исключения. Подать каждый случай через pytest-httpserver или respx. Зафиксировать несоответствия. Для 6.4 применить чек-лист actionability: (а) что случилось, (б) где, (в) что делать, (г) куда обратиться.
Цель. Пользователь не должен утечь секреты через SDK.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 7.1 | Секреты не появляются в логах любого уровня | 2% | LA | Перехват logging, регекс-проверка по маркерам Bearer, client_secret=, Authorization |
| 7.2 | Секреты не появляются в сообщениях исключений | 1% | FI | Провокация ошибки с заведомо secret-значением в параметре |
| 7.3 | Диагностический снапшот клиента безопасен по умолчанию | 1% | AC, FI | Вызов «диагностической» функции, проверка содержимого |
| 7.4 | Сериализация публичных моделей не раскрывает внутренние поля | 1% | AC | json.dumps(model.to_dict()) по выборке моделей |
| 7.5 | bandit не выдаёт high-severity findings в публичных модулях |
1% | SA | bandit -r <package> |
Процедура. Настроить тест, перехватывающий logging на уровне DEBUG, прогнать 10 типовых сценариев, прогрепать вывод по регексам секретов. Для 7.5 — CI-интеграция bandit.
Цель. SDK переживает сетевые сбои без участия пользователя.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 8.1 | Ретраи только на безопасных сценариях | 2% | FI | Последовательности [500, 500, 200], [429, 200], [timeout, 200], [POST, 500] |
| 8.2 | Backoff экспоненциальный с jitter | 1% | FI, AM | freezegun + замер задержек между попытками, проверка дисперсии |
| 8.3 | Retry-After соблюдается на 429 |
1% | FI | Сервер возвращает 429 Retry-After: 3, проверка реальной задержки |
| 8.4 | После исчерпания ретраев — доменное исключение | 1% | FI | [500, 500, 500, 500] → не httpx.*, а доменный тип |
| 8.5 | Таймауты connect/read/write настроены явно | 1% | AC | Чтение конструктора транспорта |
| 8.6 | Конфигурируемость политики retry/timeout | 1% | AC, CB | Сравнение с stripe-python и Azure SDK |
Процедура. Подключить toxiproxy или mock-сервер с программируемой задержкой; для 8.2 — ≥5 попыток, измерить stdev(delays) > 0; для 8.3 — сравнить фактическую задержку с Retry-After ± 20%.
Цель. Безопасный повтор write-вызова не создаёт дублей.
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 9.1 | Публичные write-методы принимают idempotency_key |
1% | AC, CB (эталон — Stripe) |
| 9.2 | При ретрае ключ один на весь retry-chain | 1% | FI |
| 9.3 | Отсутствие ключа = отсутствие ретрая на non-idempotent статусах | 1% | FI |
Процедура. Сценарий [transport_error, 200] для POST: с ключом — два запроса с одинаковым header, без ключа — одна попытка и исключение.
Цель. Большие коллекции не требуют ручной склейки страниц.
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 10.1 | Lazy-контейнер возвращается по умолчанию | 1% | AC, FI |
| 10.2 | Итерация первых N элементов → ceil(N/page) запросов |
1% | FI, AM |
| 10.3 | Явная полная материализация без повторных запросов | 1% | FI |
| 10.4 | Пустая коллекция не делает лишних запросов; ошибка страницы N пробрасывается при чтении N | 1% | FI |
Процедура. Mock-сервер с N страницами: замер количества HTTP-обращений при срезе [:k], при полной материализации, при пустом ответе, при ошибке на странице 3.
Цель. Гибкость на уровне отдельного вызова без мутации клиента.
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 11.1 | timeout можно переопределить на уровне метода |
1% | AC, FI |
| 11.2 | Retry-policy можно отключить/усилить для одного вызова | 1% | AC, FI |
| 11.3 | Override не мутирует клиент и не течёт между вызовами | 1% | FI |
Процедура. Передать timeout=0.001 одному вызову, проверить, что соседний вызов с дефолтным таймаутом не пострадал.
Применимо только если SDK объявляет async-поверхность; иначе критерий отключается и вес перераспределяется пропорционально.
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 12.1 | Async и sync живут в разных namespace'ах | 1% | AC, CB |
| 12.2 | Сигнатуры идентичны (отличается только async/await) |
1% | AC, AM |
| 12.3 | Feature parity в рамках одного релиза | 1% | DA |
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 13.1 | Конфигурация из environment, явного объекта и прямых аргументов — все три пути работают | 1% | AC, TT |
| 13.2 | Priority resolution (env > .env > defaults) детерминирована и документирована |
1% | FI, DA |
| 13.3 | Отсутствие обязательных полей ловится до первого HTTP | 1% | FI |
| 13.4 | Универсальные имена env (TOKEN, SECRET) не являются официальными алиасами |
1% | DA |
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 14.1 | Все операции upstream-спеки имеют публичный метод | 2% | AM, DA |
| 14.2 | Имена полей, nullability, enum'ы совпадают со спекой | 1% | DA |
| 14.3 | Устаревшие операции явно помечены deprecation | 1% | AC, DA |
Процедура. Из OpenAPI/Swagger извлечь список operationId; сопоставить с публичными методами через таблицу соответствия; на выборке 20 моделей сверить поля со схемой.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 15.1 | Tutorial (step-by-step от нуля до первого успеха) присутствует | 1.5% | DA, TT | Прогон персоны P1 по tutorial |
| 15.2 | How-to guides на типовые задачи | 1.5% | DA | Инвентаризация готовых рецептов |
| 15.3 | Reference покрывает публичный API | 1.5% | AM | interrogate — покрытие docstring'ами |
| 15.4 | Explanations на ключевые концепты (транспорт, retry, пагинация) | 1% | DA | |
| 15.5 | CHANGELOG ведётся, связан с релизами | 0.5% | DA | |
| 15.6 | Примеры в документации исполняемы | 1% | TT | Copy-paste всех snippet'ов в venv |
Процедура. Построить матрицу Diátaxis (4 столбца, по строкам — разделы документации). Каждый раздел попадает ровно в одну ячейку. Пустые столбцы = провал.
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 16.1 | Публичный fake/mock-transport доступен из документированного namespace'а | 2% | AC, DA |
| 16.2 | Документирован контракт мока: скрипт ответов, инспекция вызовов, инъекция ошибок | 1% | DA |
| 16.3 | Публичные модели стабильно сериализуются через json.dumps без кастомных энкодеров |
1% | AM |
| 16.4 | Context-manager закрывает ресурсы, обращение после закрытия даёт понятную ошибку | 1% | FI |
Процедура. Написать «каноничный потребительский тест»: создать клиент с публичным моком, прогнать 3 сценария, сериализовать результаты в JSON, закрыть клиент, попытаться вызвать метод — зафиксировать поведение.
| # | Подкритерий | Вес | Методы | Инструменты |
|---|---|---|---|---|
| 17.1 | SDK использует стандартный logging под именованным logger'ом |
1% | AC, LA | |
| 17.2 | Структурированные поля: operation, endpoint, status, attempt, latency | 1% | LA | |
| 17.3 | Каждый сетевой вызов оставляет хотя бы одну запись на DEBUG |
1% | LA |
Процедура. Включить logging на DEBUG, прогнать 5 типовых сценариев, выгрузить записи в JSON-lines, проверить наличие полей и отсутствие секретов.
| # | Подкритерий | Вес | Методы |
|---|---|---|---|
| 18.1 | Semver соблюдается (breaking → major, additive → minor, fix → patch) | 1% | DA |
| 18.2 | Deprecation-период явный, не менее двух минорных релизов | 1% | DA |
| 18.3 | Устаревшие символы выдают DeprecationWarning с ссылкой на замену |
1% | AC, FI |
| 18.4 | CHANGELOG содержит секции Added/Changed/Deprecated/Removed/Fixed |
1% | DA |
| 18.5 | Публичные переименования всегда проходят через alias с warning'ом | 1% | AC, DA |
Процедура. Взять последние 3–5 релизов; для каждого — сопоставить характер изменений с версионированием. Импортировать устаревшие символы, проверить DeprecationWarning.
Рекомендуемая длительность полного цикла — 1–2 дня на одного оценщика; 3–4 дня с участием пользователей.
- Чистый venv, фиксация SHA/версии SDK.
- Установка инструментов из §5.
- Создание рабочей папки
evaluation/<sha>/для артефактов.
Последовательно прогнать и сохранить вывод:
ruff check,ruff format --checkmypy --strictилиpyright --strictbandit -rvultureinterrogate- собственный скрипт сравнения upstream-спеки с публичным API
Заполнить все подкритерии с методом SA/AM.
- Построить матрицу Diátaxis.
- Сверить список env-переменных в документации с фактическим поведением.
- Пройти CHANGELOG за последние релизы.
- Проверить исполняемость всех snippet'ов из документации.
- Поднять
pytest-httpserverилиrespx. - Прогнать матрицы:
(статус × сценарий) → ожидаемое поведение. - Зафиксировать результаты в таблицу.
- P1 получает канонический онбординг-таск.
- P2 получает задачу «напиши тест поверх SDK».
- P3 (при наличии — опционально по diary study) фиксирует инциденты обновления версий.
- Запись экрана, протокол think-aloud.
По 10 эвристикам DX (§5.5). Каждая эвристика даёт короткий observation + ссылку на затронутые подкритерии.
Выбрать 2–3 эталонных SDK из §5.6. На тех же сценариях зафиксировать расхождения.
- Заполнить итоговую таблицу
criterion × subcriterion × grade × evidence. - Вычислить
Score. - Вычислить
Painдля каждого подкритерия сgrade < 0.75. - Отсортировать backlog.
- Оформить отчёт по шаблону §27.
Фиксированная структура, чтобы результаты сравнимы между релизами.
- Score:
XX%(категория: эталонный / рабочий / долг / рефакторинг). - Дата оценки, версия SDK, имя оценщика.
- Топ-3 выводов в 1–2 предложениях.
Колонки: #, критерий, вес, средневзвешенный балл, вклад в Score, тренд (↑/↓/→ относительно предыдущей оценки).
Для каждого критерия:
- Баллы подкритериев с кратким обоснованием.
- Доказательство (
evidence) — ссылка на лог, скриншот, цитата сообщения, запись сессии. Без указания конкретных имён файлов из исходников — описывается поведение, не локация. - Что даст +25% на следующую оценку.
Таблица: #, наблюдение, подкритерий, Pain, оценка трудоёмкости исправления, рекомендация.
- Сырые выводы инструментов (
ruff.txt,mypy.txt,bandit.json). - FI-матрица с запрошенными/полученными реакциями.
- Транскрипты персон-сессий (де-идентифицированные).
- DevSUS-анкеты.
Методика считается пригодной, если:
- Воспроизводимость. Два независимых оценщика получают
Scoreв пределах ±5% на одной ревизии. - Стабильность Pain-ranking. Топ-10 подкритериев по
Painсовпадает между сессиями ≥80%. - Автоматизация. Каждый подкритерий имеет хотя бы один объективный источник данных (SA/FI/DA/AM/CB). Чисто субъективных подкритериев нет.
- Предсказательность. Выполнение всех рекомендаций из backlog даёт прирост
Scoreне меньше суммы весов соответствующих подкритериев. - Переносимость. Методика применима к любому Python-SDK без изменений, кроме отключения критерия 12 (async/sync parity), если SDK синхронный.
- Ежеквартально для стабильных SDK.
- Перед каждым major-релизом как гейт выпуска.
- После любой архитектурной перестройки публичного API.
- После появления negative feedback от пользователей — целевая оценка критериев, на которые указал feedback.
Результаты — Score, дельта, Pain-топ — публикуются в release notes как часть описания качества релиза.