Skip to content

Releases: r1natt/vk_social_graph

Refactoring

23 Jul 09:03

Choose a tag to compare

Цели рефакторинга заключались в создании устойчивой, расширяемой и легко поддерживаемой архитектуры проекта. Для этого были реализованы следующие подходы:

1. Максимальное соответствие принципам SOLID

SOLID включает в себя 5 основных принципов, которые были описаны Робертом Мартиным. Подход чистого кода подразумевает простой подход к дополнению и обслуживанию написанного ПО (по его задумке).

Данный рефакторинг частично выполнялся с отсылкой на книгу "Чистый код", чтобы дальнейшее дополнение существующего кода проходила быстрее и эффективнее.

2. Разделение на модули

Кодовая база структурирована по смысловым модулям:

  • запросы (utils/reqs.py).
  • работа с базой данных (db/).
  • парсинг (service/), включает в себя парсинг вк и составление графа.

3. Обдуманный выбор имён

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

Подробнее про каждую логику

Модели данных и обмен информацией между модулями

В проекте реализован новый подход к обмену данными между модулями. Для этого используются следующие инструменты:

  • Pydantic-модели

Все основные структуры данных (ответы API, записи в базе) описаны через pydantic-модели (BaseResponse, FriendsResponse, UserResponse, BaseRecord, FriendsRecord, UserRecord).

  • Dataclass

Для описания структур, связанных с обработкой ошибок и ответов API (например, APIError, APIResponse), используются dataclass.

Это облегчило создание простых контейнеров данных с минимальным количеством кода.

  • Enum

Для определения констант, статусов, типов запросов и ресурсов API применяются перечисления (Enum, IntEnum).

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

Модуль запросов (utils/reqs.py)

Архитектура и принципы

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

Основные компоненты

1. Абстракции и интерфейсы

  • RequestTracker / SynchronousRequestTracker

Абстракция и синхронная реализация трекера частоты запросов (RPS).

Вместо отдельного процесса (как было с TPS bucket), теперь лимит запросов реализован через очередь с временными метками прямо в основном процессе.

Это упрощает архитектуру и устраняет накладные расходы на межпроцессное взаимодействие.

  • ErrorClassifier / VKAPIErrorClassifier

Абстрактный и конкретный классы для классификации ошибок VK API по степени критичности и возможности повторной попытки.

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

  • ResponseParser / JSONResponseParser

Интерфейс и реализация для парсинга HTTP-ответов.

Позволяет отделить логику разбора ответа от остального кода, что облегчает тестирование и замену формата ответа.

  • RetryStrategy / ExponentialBackoffRetryStrategy

Интерфейс и реализация стратегии повторных попыток с экспоненциальной задержкой.

Позволяет гибко управлять политикой повторов при ошибках.

2. Клиенты и интерфейсы

  • APIClient

Универсальный клиент для выполнения HTTP-запросов с поддержкой трекинга RPS, обработки ошибок, повторных попыток и парсинга ответов.

Все зависимости внедряются через конструктор.

  • VKAPIClient

Специализированный клиент для VK API, использующий все вышеописанные абстракции.

Инкапсулирует базовый URL, параметры авторизации и версию API.

  • VKAPIInterface / VKAPICodeInterface

Высокоуровневые интерфейсы для работы с VK API: получение друзей, пользователей, а также выполнение кода на VKScript через метод execute.

Используют конвертеры для преобразования ответов в pydantic-модели.

  • APIResponseToPydanticConverter

Класс для преобразования "сырых" ответов API в pydantic-модели (FriendsResponse, UserResponse), что облегчает дальнейшую работу с данными.

Ограничение частоты запросов (RPS/TPS)

Практически все API имеют лимит запросов за промежуток времени.
Ранее для ограничения частоты запросов использовался отдельный процесс с TPS bucket (Token Bucket), что приводило к дополнительным накладным расходам на межпроцессное взаимодействие.

Теперь реализован синхронный RPS tracker, который отслеживает количество запросов непосредственно в основном процессе.

Такой подход упрощает архитектуру и делает поведение системы более предсказуемым.

Итоги

В результате модуль стал легко расширяемым, тестируемым и соответствующим современным архитектурным стандартам.

Запросы были переработаны с учетом принципов SOLID. Ответственность разделена между абстрактными базовыми классами и конкретными реализациями, каждая из которых отвечает только за свою зону ответственности.

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

Вся логика работы с запросами стала более атомарной и расширяемой.

Работа с базой данных (db/db.py)

Основные компоненты

  1. MongoMethods

Ранее вся работа парсера с бд осуществлялась через единый класс, в котором были методы ко всем коллекциям. Сейчас операции с коллекциями выделены в отдельный объект MongoMethods, а все функции более высокого уровня выделены в отдельные объекты, которые наследуются от MongoMethods.

  1. Коллекции данных (FriendsCollection, UserCollection)

FriendsCollection

Класс для работы с коллекцией друзей пользователя.

  • Поддерживает политику обновления: если включена, обновляет существующую запись, иначе создает новую.

  • Ведет историю посещений и отслеживает изменения в списке друзей (добавление, удаление, восстановление).

  • Логика обновления реализована через отдельные методы для вычисления восстановленных и удалённых друзей, а также для фиксации новых визитов.

UserCollection

Класс для работы с коллекцией пользователей.

  • Сохраняет новых пользователей, если их еще нет в базе.

  • Ведет историю посещений пользователя.

  1. Фабрика коллекций

Класс-фабрика для создания экземпляров коллекций (FriendsCollection, UserCollection) с нужными параметрами (например, политика обновления, период обновления).

  • Позволяет централизованно управлять созданием и сбросом коллекций.
  • Поддерживает возможность сброса всех коллекций (например, для тестирования или инициализации).

Парсинг и обход графа (service/)

Раньше для парсинга и обхода графа использовалась рекурсивная реализация. Такой подход затруднял отслеживание состояния обхода, усложнял отладку, сопровождение и масштабирование алгоритма (особенно при глубоком обходе из-за риска переполнения стека).

Теперь реализован отдельный модуль с универсальным алгоритмом обхода графа (BFS — поиск в ширину), который инкапсулирован в абстрактном классе и его наследниках.

Это позволило явно контролировать очередь обхода и посещённые вершины, расширять и переиспользовать алгоритм для разных задач (парсинг, построение графа для визуализации и т.д.);

Основные компоненты

  1. Алгоритм обхода графа (service/graph_search.py)
  • GraphSearch (ABC):

Абстрактный базовый класс для реализации различных стратегий обхода графа.

  • BFS:

Класс реализует обход графа в ширину с помощью приоритетной очереди и явного хранения посещённых вершин.

Метод search принимает стартовый VK ID и максимальную глубину обхода, а также вызывает абстрактный метод action для обработки каждой вершины.

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

  • UserTask:

Структура для хранения информации о текущей задаче обхода (ID пользователя и глубина обхода).

  1. Парсер данных (service/parser.py)
  • VKParser (наследник BFS):

Класс для парсинга данных о пользователях и их друзьях с помощью обхода графа.

  • Использует интерфейсы для работы с запросами и коллекциями БД.

  • В методе action для каждой вершины (пользователя) получает и сохраняет информацию о пользователе и его друзьях.

  • Логика получения и сохранения данных инкапсулирована в отдельных методах (get_user, get_friends).

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

  1. Формирование графа для визуализации (service/gephi.py)
  • GexfGraph (наследник BFS):

Класс для построения графа пользователей и их связей с последующим экспортом в форматы, поддерживаемые Gephi (GEXF, GML, GraphML).

  • В методе action для каждой вершины добавляет узел и рёбра в граф, используя данные из БД.

  • Реализованы методы для фильтрации узлов по степени, задания цвета в зависимости от расстояния, и сохранения графа в файл.

Такой подход позволяет быстро и гибко формировать графы для анализа и визуализации.

First release!

08 Feb 21:56

Choose a tag to compare

This the first release with minimal functional of save friends relationships and creating graph of user relations