Настройки чтения
Размер шрифта
Высота строк
Поля
На страницу:
4 из 4

Средний промпт. Разработчик, наученный горьким опытом, пишет: «Нужен модуль авторизации на Python с FastAPI. Используй JWT. Храни пользователей в PostgreSQL. Пароли должны хешироваться». Модель возвращает рабочий код. Но всё ещё сырой: схема базы создана, но миграций нет; access token живёт вечно, нет механизма обновления; нет rate-limiting; нет логирования попыток входа; секретный ключ для JWT читается из переменной окружения, но без пояснения, как его генерировать. Этот код можно запустить, и он даже будет работать. Но в production он создаст дыры в безопасности и неудобства в поддержке.

Идеальный промпт. Теперь мы применяем наш шаблон. Это займёт полторы-две страницы текста, но результат будет пригоден к деплою с минимальными правками. Выглядит это примерно так.

Контекст: «Мы разрабатываем backend для сервиса доставки еды. Стек: Python 3.11, FastAPI, SQLAlchemy 2.0 с async, PostgreSQL 15, Redis для сессий. В проекте уже принята модульная структура: каждый домен лежит в своей папке со своими моделями, сервисами и роутами. Аутентификация должна быть выделена в модуль identity. В проекте используется гексагональная архитектура: модели домена не зависят от базы данных, репозитории реализуют интерфейсы, описанные в доменном слое. Соглашение о нейминге: эндпоинты в kebab-case, функции в snake_case, классы в PascalCase. Все ошибки API возвращаются в формате JSON с полями error_code и message. У нас уже есть модель User с полями id, email, password_hash, is_active, failed_login_attempts, locked_until. Она лежит в modules/identity/domain/user.py».

Цель: «Реализовать API-эндпоинт POST /auth/login, который принимает JSON с полями email и password. Требования: проверить, что пользователь с таким email существует, и что он активен (is_active == True); если пользователь заблокирован — вернуть ошибку 423 с соответствующим сообщением и кодом USER_LOCKED; сравнить пароль через bcrypt; при неверном пароле инкрементировать failed_login_attempts, и если попыток стало 5 — установить locked_until на текущее время плюс 15 минут и вернуть ошибку 423 с кодом USER_LOCKED; при успешном входе сбросить failed_login_attempts в 0, создать access token через JWT со сроком жизни 15 минут и refresh token со сроком жизни 7 дней; access token вернуть в теле ответа, refresh token установить в http-only secure куку; логировать каждую попытку входа — успешную и неуспешную — с полями user_id, ip_address, timestamp, success (bool) через вызов logger.info* с экранированием персональных данных; написать постусловие: после успешного входа пользователь должен иметь валидную сессию, проверяемую через эндпоинт GET /auth/me».

* Сам по себе logger.info — это команда (вызов метода), которая используется в программировании для записи информационного сообщения в лог (журнал событий).

Чтобы понять, что именно это значит, нужно разобрать его по частям:

1. logger (объект)


Это специально созданный объект в коде, который отвечает за логирование. Он обычно настраивается один раз в начале программы (с помощью библиотек типа logging в Python, log4j в Java, winston в JavaScript и т.д.).

2. .info() (метод)


Это функция, которая говорит логгеру: «Запиши это сообщение, но пометь его как информационное (Information)».

Какой смысл у уровня INFO ?

В логировании есть уровни важности (по возрастанию серьезности):

DEBUG — для отладки (мельчайшие детали, что происходит внутри функций).

INFOинформационные сообщения (ход выполнения бизнес-процессов, важные этапы работы).

WARNING — предупреждения (что-то пошло не так, но программа работает дальше).

ERROR — ошибки (функция не выполнилась, но программа жива).

CRITICAL — критические ошибки (программа падает).

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

Пример на Python (для наглядности)

python

import logging


# Настраиваем логгер

logging.basicConfig(level=logging.INFO)

logger = logging.getLogger(__name__)


def transfer_money(user, amount):

logger.info(f"Начинаем перевод {amount} рублей для пользователя {user}") # <-- Это logger.info

# ... какой-то код ...

logger.info(f"Перевод для {user} успешно завершен") # <-- И это logger.info

Если вы запустите код, в консоли вы увидите что-то вроде:


INFO:__main__:Начинаем перевод 100 рублей для пользователя Alex

Что происходит под капотом?

Когда вызывается logger.info("Текст"), происходит следующее:

Создается объект "событие" (LogRecord) с текущим временем, именем файла, строкой кода и вашим текстом.

Логгер проверяет, разрешен ли уровень INFO в настройках (если стоит уровень WARNING, то сообщение INFO не будет показано).

Сообщение передается в Handler (обработчик), который решает, куда его отправить: в консоль, в файл на диске, в базу данных или в систему мониторинга (например, Sentry или ELK).

Что обычно пишут в logger.info ?

Хороший тон — писать:

Начало и конец важных операций (например, "Загрузка файла начата", "Загрузка завершена").

Ключевые бизнес-события (например, "Пользователь зарегистрирован", "Заказ оплачен").

Изменения состояния системы (например, "Сервис перезапущен", "Кэш очищен").

Важно: В INFO не пишут пароли, токены доступа или персональные данные (кроме ID пользователя), так как эти логи часто хранятся в открытом виде.

****

Стиль: «Следуй гексагональной архитектуре. Интерфейсы репозиториев уже определены в доменном слое, используй их — не создавай новые. Внедрение зависимостей через конструкторы сервисов. Код должен быть покрыт type hints. Используй Pydantic для схем запросов и ответов. JWT должен подписываться алгоритмом RS256, приватный ключ читается из settings.JWT_PRIVATE_KEY».

Аудитория: «Код будет поддерживаться мидл-разработчиками, которые знакомы с FastAPI, но не являются экспертами в криптографии. Поэтому в сложных местах добавь краткий комментарий, объясняющий, почему выбран именно этот подход. Но не комментируй очевидное».

Формат ответа: «Выведи три файла: modules/identity/api/auth_router.py с эндпоинтами, modules/identity/services/auth_service.py с бизнес-логикой, modules/identity/schemas/auth_schemas.py с Pydantic-моделями. Каждый файл начни с импортов. Код должен запускаться без ошибок при условии, что все зависимости, указанные в контексте, уже установлены. В конце ответа приведи список допущений, которые ты сделал при реализации, если тебе не хватило информации».

Ограничения: «Не используй библиотеку python-jose — используй PyJWT. Не создавай новых моделей базы данных. Не меняй существующую структуру папок. Не добавляй middleware — у нас он уже есть на уровне API Gateway. Если потребуется новая зависимость, явно укажи это в списке допущений».

Разница в выхлопе между плохим и идеальным промптом колоссальна. Плохой промпт даёт код, который нужно переписывать. Средний — код, который нужно допиливать. Идеальный — код, который можно ревьюить, а не переписывать. Экономия времени не на этапе написания промпта — идеальный промпт пишется дольше плохого. Экономия на этапе работы с результатом. Вы тратите десять минут на написание идеального промпта, чтобы не тратить два часа на правку сгенерированного кода.

Здесь важен ещё один мета-навык, который приходит с практикой: умение определять, насколько подробным должен быть промпт для конкретной задачи. Не каждая задача требует двух страниц спецификации. Если вы пишете утилиту для форматирования дат — контекст и ограничения минимальны. Если вы проектируете модуль аутентификации — промпт должен быть исчерпывающим. Правило простое: объём промпта должен быть пропорционален стоимости ошибки в сгенерированном коде. Ошибка в форматировании даты видна сразу и правится за секунду. Дыра в аутентификации может стоить компании репутации и штрафов. Поэтому идеальный промпт для аутентификации — это не перфекционизм, а соразмерная осторожность.

Конец ознакомительного фрагмента.

Текст предоставлен ООО «Литрес».

Прочитайте эту книгу целиком, купив полную легальную версию на Литрес.

Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.

Конец ознакомительного фрагмента
Купить и скачать всю книгу
На страницу:
4 из 4