501просмотров
32.7%от подписчиков
16 февраля 2026 г.
📷 ФотоScore: 551
🤖 Архитектура Telegram‑бота: структура проекта, чистый код и тесты (чтобы не превратить бота в “лапшу”) Если бот живёт дольше 2–3 дней, в нём неизбежно появляется: “быстро поправлю тут”, “временно вот так”, “потом разберусь”. Через месяц это уже не бот, а квест. Ниже - практичный шаблон, который помогает держать код чистым и масштабировать проект без боли. 1️⃣ Главный принцип: разделяй “что бот делает” и “как он общается с Telegram” ❌ Плохой знак: в хендлере 200 строк 0-и там же запросы в БД, логика, тексты, API, платежи. ✅ Хороший знак: хендлер - это тонкий слой: принял апдейт → вызвал сервис → отдал ответ. Мини‑правило: - Handlers (Delivery layer) - только роутинг/валидация/ответы - Services (Use cases) - бизнес‑логика - Repositories (Data access) - БД/файлы/кэш - Clients (Integrations) - внешние API - DTO/Schema - типы входов/выходов между слоями 2️⃣Пример структуры проекта (универсально) Подойдёт и для aiogram, и для других фреймворков: bot/ app/ # точка входа, настройка приложения main.py config.py logging.py handlers/ # обработчики команд/сообщений/кнопок start.py orders.py keyboards/ # кнопки/меню main.py texts/ # тексты/шаблоны сообщений ru.py services/ # бизнес-логика (use cases) order_service.py user_service.py repositories/ # доступ к данным user_repo.py order_repo.py clients/ # внешние интеграции payments.py crm.py models/ # модели домена / ORM user.py order.py schemas/ # DTO / валидация (pydantic и т.п.) order.py utils/ # утилиты time.py formatters.py tests/ test_order_service.py 3️⃣Чистые хендлеры: пример “как должно быть” Хендлер - короткий, читабельный, без “магии”: # handlers/orders.py async def create_order(message, order_service): user_id = message.from_user.id text = message.text order = await order_service.create_order(user_id=user_id, raw_text=text) await message.answer(f"Заявка #{order.id} принята") А вся логика - в сервисе: # services/order_service.py class OrderService: def init(self, order_repo, anti_spam): self.order_repo = order_repo self.anti_spam = anti_spam async def create_order(self, user_id: int, raw_text: str): self.anti_spam.check(user_id) parsed = self._parse(raw_text) return await self.order_repo.create(user_id=user_id, **parsed) def _parse(self, raw_text: str) -> dict: # парсинг/валидация/нормализация return {"title": raw_text.strip()[:120]} Почему это важно: сервисы проще тестировать, переиспользовать и менять. 4️⃣ Best practices, которые реально экономят время Конфиг - только через переменные окружения Токены, ключи, URL - не в коде. Делай config.py, который читает env. Логи вместо print Логи должны отвечать на 3 вопроса: - что произошло? - кого (user_id/чат)? - чем закончилось (успех/ошибка)? Тексты отдельно от логики Сегодня “Привет”, завтра - “Здравствуйте”, послезавтра - 2 языка. Если тексты смешаны с кодом - боль гарантирована. Единый стиль ошибок Определи свои исключения: ValidationError, NotFound, ExternalApiError — и в одном месте решай, как отвечать пользователю. 5️⃣ Тесты: что тестировать в боте в первую очередь Тестировать Telegram API “в лоб” часто тяжело и не нужно. Тестируй бизнес‑логику (services): - парсинг и валидация входных данных - расчёты, условия, ограничения - работа с репозиториями через моки - сценарии ошибок (API упало, лимит превышен, пользователь не найден) 6️⃣Чек‑лист “бот готов к росту” Хендлеры тонкие, логика в сервисах Есть единая структура папок Конфиг через env, секретов в репо нет Тексты вынесены отдельно Логи есть, print нет Есть тесты хотя бы на ключевые сервисы Интеграции изолированы в clients/ Хотите бота без боли - купите бота у меня. Пишите в личку: “Хочу бота” - и коротко опишите задачу (для чего бот и что он должен
501
просмотров
4000
символов
Да
эмодзи
Да
медиа

Другие посты @dev_svyatoslav

Все посты канала →
🤖 Архитектура Telegram‑бота: структура проекта, чистый код — @dev_svyatoslav | PostSniper