У меня был старый скрипт синхронизации VirtueMart с VK Market. Написанный очень давно, он работал неплохо, но с одним огромным недостатком — он был очень медленным. Скрипт обновлял товары целиком, даже если ничего не менялось. Синхронизация всех товаров могла занимать более 30 минут.

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

Тогда пришла мысль о рефакторинге. И это решение помогло не только навести порядок в коде, но и разобраться с множеством проблем, которые копились годами.


Проблемы старого скрипта

1. Медленная работа

Скрипт обновлял все товары целиком, даже если ничего не изменилось. Это приводило к огромному количеству лишних запросов к VK API и к долгой синхронизации.

2. Монолитная структура

Весь код был в одном файле. Одна функция делала всё: подключалась к БД, выполняла запросы, загружала фото, обновляла товары. Найти ошибку в такой структуре было почти невозможно.

3. Нет контроля изменений

Скрипт не умел определять, что именно изменилось в товаре. В результате обновлялись все поля, даже те, которые не менялись.

4. Проблемы с API VK

Со временем VK изменил свой API, и скрипт перестал корректно работать. Например, поле stock_amount перестало возвращаться в массовых запросах, а old_price стал храниться внутри price.

5. Сложность анализа

Когда код разросся до 1700+ строк, понять логику его работы стало невозможно. Любое изменение могло сломать что-то в другом месте.

Первые два дня: добавление логики

Первые два дня я пытался просто добавить логику в существующий монолитный скрипт. Исправлял проблемы с остатками, добавлял проверку цен, улучшал работу с изображениями.

К концу второго дня код выглядел страшно:

mi55_to_vk_bot.py
├── 1700+ строк кода
├── 5 больших функций
├── Нет никакой структуры
├── Невозможно понять логику
└── Страшно менять

Я понял: если продолжать в том же духе, скрипт превратится в неподдерживаемый монстр. Нужно было кардинально менять подход.


День третий: Рефакторинг

На третий день я принял решение: переписать скрипт с нуля, но с правильной архитектурой. Главное, что я хотел получить — возможность чётко видеть, что именно происходит на каждом этапе.

Архитектурное решение: Этапы синхронизации

Я разделил процесс на три чётких этапа. Теперь каждый этап занимается только своим делом:

1. Сбор данных (только чтение, никаких изменений)
   ↓
2. Планирование (сравнение, принятие решений)
   ↓
3. Выполнение (только запланированные действия)

Этот подход кардинально изменил ситуацию. Теперь я мог видеть, что именно пошло не так, и исправлять проблему локально, не трогая остальной код.

Структура проекта после рефакторинга

mi55_to_vk_bot/
├── main.py              # Только точка входа, запуск этапов
├── config.py            # Конфигурация и константы
├── models.py            # Dataclass — чёткие структуры данных
├── db.py                # Только работа с БД
├── vk_api.py            # Только запросы к VK
├── prices.py            # Вся логика работы с ценами
├── images.py            # Только работа с изображениями
├── sync.py              # Планирование синхронизации
├── executor.py          # Выполнение плана
├── operations.py        # Операции с VK (создать, обновить, скрыть)
├── email_report.py      # Отчёты по email
└── utils.py             # Вспомогательные функции

Каждый модуль отвечает за свою зону ответственности. Мне больше не нужно лезть в логику работы с ценами, чтобы исправить что-то в изображениях.


Что дал рефакторинг

1. Прозрачность

Теперь я вижу, что происходит на каждом этапе. Скрипт выводит детальные логи:

📊 План синхронизации:
  ➕ Создать: 0
  🔄 Обновить: 8 (цены, остатки)
  ➖ Без изменений: 629
  ⏭️ Пропущено (без остатка): 2841

2. Умные обновления

Скрипт теперь сравнивает данные из БД и VK и обновляет только то, что действительно изменилось. Товары перестали обновляться каждый раз без причины.

3. Работа с одним товаром

Появилась возможность синхронизировать один товар, что сильно упростило отладку.

python main.py 12592

4. Email-отчёты

Теперь после каждой синхронизации приходит письмо с полной статистикой. Ошибки не остаются незамеченными.

5. Обработка крайних случаев

Рефакторинг помог найти и исправить множество скрытых проблем:

  • VK не возвращает stock_amount в массовых запросах
  • old_price лежит внутри price как old_amount
  • VK не принимает old_price если она меньше или равна price
  • Неопубликованные товары нужно скрывать, а не создавать

Сравнение: до и после

Параметр До рефакторинга После рефакторинга Улучшение
Время синхронизации ~30 минут ~2 минуты 15x
API-запросов на товар 7-10 2-3 3x
Обновление товара Всегда Только при изменениях ~98% экономии
Строк кода 1700+ 2700 (в 14 модулях) Структурировано
Возможность отладки Практически нет Детальные логи + email

Ключевые технические находки

1. VK не возвращает stock_amount в market.get

При массовой загрузке товаров VK не отдаёт поле stock_amount. Вместо этого нужно использовать availability:

availability = item.get("availability", 0)
stock = 999999 if availability == 0 else 0

2. old_price хранится внутри price

VK хранит старую цену как old_amount внутри объекта price:

price_data = item.get("price", {})
old_price = price_data.get("old_amount")  # А не item.get("old_price")

3. VK проверяет old_price > price

VK возвращает ошибку, если old_price меньше или равна price. Нужно проверять это перед отправкой:

if product.old_price is not None and product.old_price > product.price:
    data["old_price"] = product.old_price

4. Неопубликованные товары

Товары с published = 0 должны скрываться в VK, а не создаваться:

if db_product.published == 0:
    if vk_product:
        plan.to_hide.append(db_product)
    continue

Что я вынес из этого опыта

  1. Никогда не пиши большие монолитные скрипты. Как только код превышает 500 строк в одном файле — начинай рефакторинг. Это окупится с лихвой.

  2. Разделяй на этапы. Процесс синхронизации — это идеальный кандидат для разделения на этапы. Это делает код прозрачным и легко отлаживаемым.

  3. Используй dataclass. Чёткие структуры данных помогают не запутаться в том, какие данные ты обрабатываешь.

  4. Добавляй email-отчёты. Когда скрипт работает на сервере, единственный способ узнать о проблемах — это получить письмо.

  5. Читай документацию VK. Я потратил много времени на поиск проблем, описанных в документации. Всё, что нужно, там уже есть.

  6. Рефакторинг — это не страшно. Когда код становится неудобным, переписывание с нуля с правильной архитектурой может сэкономить дни отладки в будущем.


Результат

Теперь скрипт работает быстро и предсказуемо:

  • 4826 товаров синхронизируются за ~2 минуты
  • Обновляются только товары с реальными изменениями
  • Все ошибки логируются и отправляются по email
  • Отчёт приходит сразу после синхронизации
  • Любой этап можно отладить отдельно

Вместо 1700+ строк в одном файле — 14 модулей по 100-400 строк. Вместо непонятного монстра — прозрачная и поддерживаемая архитектура.


Заключение

Иногда лучшее решение — это переписать код с нуля, используя правильную архитектуру. Три дня работы над рефакторингом сэкономили недели будущих проблем.

Если ваш скрипт стал большим и непонятным — не бойтесь рефакторинга. Разбейте на модули, разделите на этапы, сделайте код прозрачным. Это окупится быстрее, чем вы думаете.


P.S. Исходный код доступен в репозитории.