Опубликовано
Когда сеньор-дев смотрит твой код и молчит
Автор: Гусев Николай [портфолио]
Дата обновления не указана в исходнике.
Темы: code-review, ai-agents
Когда сеньор-дев смотрит твой код и молчит
Ты написал 400 строк. Он смотрит. Молчит. Потом одну стирает. Потом ещё три. Потом говорит: "Запускай".
Это Ponytail. Не человек - набор правил для AI-агентов, который заставляет думать перед тем как писать. Репозиторий на GitHub, MIT лицензия, 80-94% меньше кода по бенчмаркам.
Лестница, по которой нужно подниматься
Идея простая. Перед тем как написать код, остановись на первой ступеньке, которая работает:
- Нужно ли это вообще? (YAGNI) 2. Стандартная библиотека уже делает это? 3. Нативная фича платформы покрывает? 4. Установленная зависимость решает? 5. Можно в одну строку? 6. Только потом - минимальный код
Звучит очевидно. Но когда AI-агент пишет код, он прыгает сразу к шагу 6. И вот тут начинается веселье.
Пример из жизни: валидация email
Задача: проверить что email корректный. Вот что выдаёт обычный AI-агент без Ponytail:
`class EmailValidator:
def __init__(self):
self.errors = []
def validate(self, email):
self.errors = []
if not isinstance(email, str):
self.errors.append("Email must be a string")
return False
if not email:
self.errors.append("Email cannot be empty")
return False
if '@' not in email:
self.errors.append("Email must contain @")
return False
local, _, domain = email.partition('@')
if not local:
self.errors.append("Local part cannot be empty")
return False
if not domain:
self.errors.append("Domain cannot be empty")
return False
if '.' not in domain:
self.errors.append("Domain must contain a dot")
return False
if domain.startswith('.') or domain.endswith('.'):
self.errors.append("Domain cannot start or end with a dot")
return False
if '..' in domain:
self.errors.append("Domain cannot contain consecutive dots")
return False
tld = domain.rsplit('.', 1)[-1]
if len(tld) < 2:
self.errors.append("TLD must be at least 2 characters")
return False
if not tld.isalpha():
self.errors.append("TLD must contain only letters")
return False
return True
def get_errors(self):
return self.errors
def get_error_string(self):
return "; ".join(self.errors)
def is_valid_gmail(self):
return self.validate(self.email) and self.email.endswith('@gmail.com')
def is_valid_corporate(self):
free_domains = ['gmail.com', 'yahoo.com', 'hotmail.com']
return self.validate(self.email) and not any(
self.email.endswith(f'@{d}') for d in free_domains
)`
40 строк. Класс. Два публичных метода, которые никто не вызовет. Проверка TLD на длину 2+ символа - а как быть с .io? Метод is_valid_gmail - серьёзно? Это называется "абстракция с одним потребителем".
Вот тот же код с Ponytail:
`def is_valid_email(email):
# ponytail: regex for RFC compliance; re.fullmatch if you need the real thing
return isinstance(email, str) and '@' in email and '.' in email.split('@')[1]`
Одна строка. Потому что настоящая валидация - это отправить письмо и проверить что дошло. Всё остальное - театр.
Ещё один пример: кэширование API-ответов
Без Ponytail агент напишет класс ResponseCache с TTL, потокобезопасностью, метриками и методом invalidate. 40 строк.
С Ponytail:
`from functools import lru_cache
@lru_cache(maxsize=1000)
def fetch_data(url):
return requests.get(url).json()`
Одна декоратор. Встроенная библиотека. Ноль багов. Ноль CVE. 100% uptime с момента создания Python.
Не только код: YAGNI для решений и архитектуры
Вот где становится интереснее. Лестница Ponytail работает не только для кода - она работает для любого инженерного решения. Выбор стека, архитектура, процессы. Всё то же самое: остановись на первой ступеньке.
Пример: "Нам нужен Kubernetes"
Команда из 3 человек, монолит на FastAPI, одна база данных. Кто-то говорит: "Нам нужен Kubernetes для масштабирования".
Лестница Ponytail:
- Нужно ли это? Нет. У вас 100 пользователей. 2. Стандартная библиотека? systemd + nginx покрывают 99% потребностей. 3. Нативная фича платформы? Docker Compose - это уже оркестрация. 4. Установленная зависимость? Уже есть Docker.
Kubernetes - это шаг 6. И до него ещё дойти надо. Реальная история: команда потратила 3 месяца на разворачивание кластера, который обслуживал 50 запросов в минуту. На Docker Compose это бы заняло 2 дня.
Пример: "Давайте перепишем на Rust"
Сервис на Python работает. Не идеально, но работает. Кто-то предлагает переписать на Rust ради производительности.
Лестница:
- Нужно ли? Профайлер показал что 95% времени - это запросы к базе, а не Python-код. 2. Стандартная библиотека?
asyncpgвместоpsycopg2даёт 3x ускорение без переписывания языка. 3. Нативная фича? Кэширование через Redis убирает 60% запросов к базе.
Переписывание на Rust - это шаг 6. А ступеньки 1-3 уже дают 10x улучшение без смены языка.
Пример: "Нам нужен отдельный сервис для уведомлений"
Монолит растёт. Кто-то предлагает вынести уведомления в отдельный микросервис.
Лестница:
- Нужно ли? Уведомлений 50 в час. Одна функция в монолит справляется. 2. Стандартная библиотека?
asyncio.create_task- неблокирующая отправка, не нужен отдельный сервис. 3. Нативная фича? Очередь задач в том же процессе черезasyncio.Queue.
Отдельный микросервис - это шаг 6. И он добавляет: сетевые вызовы, сериализацию, мониторинг, деплой, логи. Ради 50 уведомлений в час.
Связь с Prism и Premortem
Ponytail - не изолированный скилл. Он из той же семьи что и Prism (структурный анализ) и Premortem (предварительный разбор рисков). Все три отвечают на один вопрос: "Что пойдёт не так если мы не подумаем?"
-
Prism - анализ артефакта: где слабые места, когда сломается, почему
-
Premortem - анализ плана: что пойдёт не так если начнём делать
-
Ponytail - анализ решения: нужно ли вообще делать, и можно ли проще
Вместе они закрывают три этапа: понять текущее (Prism), предсказать будущее (Premortem), не переусложнить решение (Ponytail).
Как это работает на практике
Ponytail - не линтер. Это способ мышления. Он не говорит "твой код плохой". Он спрашивает: "А нужен ли он вообще?"
Три режима работы:
-
Lite - построил как просили, но упомянул что можно проще
-
Full (по умолчанию) - лестница принудительна, stdlib и нативные фичи первыми
-
Ultra - экстремист YAGNI. Удаление прежде добавления. Вызов требованиям
И маркер для каждого сокращения: ponytail: global lock, per-account locks if throughput matters. Видно где срезали, почему, и когда переделать.
Почему это работает для AI-агентов
Проблема не в том что модели глупые. Проблема в том что они стараются. Они видят задачу и хотят сделать "правильно" - с классами, интерфейсами, фабриками. Это называется over-engineering, и он убивает проекты тише чем баги.
Ponytail даёт разрешение делать проще. Не "лень - порок", а "лень - эффективность". Лучший код - тот, который не написан. Лучшая архитектура - та, которую не пришлось строить.
Что дальше
Скилл уже интегрирован в мою работу. Каждый раз когда я принимаю решение - писать код, выбирать стек, проектировать систему - лестница активируется автоматически. Не идеально - но лучше чем ничего.
Попробуйте сами: github.com/DietrichGebert/ponytail. Установка - одна команда. Результат - меньше кода, меньше багов, меньше 3амен в продакшене.