Files
elmprodvpn/docs/phase-f/F1_REFACTOR_MODULARITY_PLAN.md

9.6 KiB
Raw Permalink Blame History

F1 План рефакторинга и модульности

Дата: 2026-03-07
Статус: planned
Владелец: Engineering

1) Цель

  • Уменьшить размер и связность крупных файлов без изменения поведения приложения.
  • Подготовить кодовую базу к быстрому развитию desktop/web/mobile поверх одного Go API.

2) Текущие "горячие" файлы

  • selective-vpn-gui/vpn_dashboard_qt.py6103 строк (до старта F1.4; после текущего разреза: 116 + main_window/ui_shell_mixin.py + main_window/singbox/* + main_window/runtime_actions_mixin.py).
  • selective-vpn-gui/api_client.py2220 строк.
  • selective-vpn-gui/dashboard_controller.py1430 строк.
  • selective-vpn-api/app/transport_handlers.go1984 строки.
  • selective-vpn-api/app/server.go (legacy) — центральная связка entrypoints/bootstrap/routes, высокий риск регрессий при точечных изменениях.

3) Принципы разрезания

  • Поведение не меняем: сначала вынос кода, потом точечные улучшения.
  • Модули режем по domain-границам, а не "по 500 строк".
  • Сохраняем один публичный entrypoint (facade) для UI и для backend-router.
  • После каждого шага прогоняем существующие smoke/e2e (без новых требований к тестам от пользователя).

4) План разрезания GUI

4.1 vpn_dashboard_qt.py -> gui/main_window/*

  • Цель: вынести табы и event-обвязку в отдельные модули.
  • Разделение:
    • main_window.py — сборка окна и общий lifecycle.
    • tabs/status_tab.py
    • tabs/vpn_tab.py
    • tabs/routes_tab.py
    • tabs/dns_tab.py
    • tabs/domains_tab.py
    • tabs/trace_tab.py
    • services/events_bridge.py (EventThread, dispatch)
    • services/locations_loader.py (LocationsThread, SWR-ui orchestration)
  • Критерий: исходный файл vpn_dashboard_qt.py становится thin-bootstrap.
  • Статус: выполнено (2026-03-10).
  • Уже сделано:
    • добавлены main_window/constants.py и main_window/workers.py (shared constants + EventThread/LocationsThread);
    • вынесен UI shell (build tabs + helpers + locations/egress) в main_window/ui_shell_mixin.py;
    • ui_tabs_singbox_mixin.py дополнительно разрезан на ui_tabs_singbox_layout_mixin.py и ui_tabs_singbox_editor_mixin.py;
    • SingBox-контур дополнительно разрезан на подпакет main_window/singbox/* (editor, cards, links, runtime) с фасадом main_window/singbox_mixin.py;
    • вынесен runtime/refresh/actions контур в main_window/runtime_actions_mixin.py;
    • проведён второй проход декомпозиции: ui_tabs_*, runtime_{state,refresh,auth,ops}, singbox/{links_*,runtime_*}; фасады оставлены для совместимости;
    • MainWindow переведён на наследование mixin-классов, поведение сохранено; в итоге крупные GUI-модули уложены в читаемые размеры (максимум ~633 строк).

4.2 dashboard_controller.py -> controllers/*

  • Разделение:
    • controllers/status_controller.py
    • controllers/vpn_controller.py
    • controllers/routes_controller.py
    • controllers/dns_controller.py
    • controllers/domains_controller.py
    • controllers/transport_controller.py
    • controllers/trace_controller.py
  • Сохраняется фасад DashboardController (совместимость с текущим UI-кодом).
  • Статус: выполнено (2026-03-10).
  • Что сделано:
    • добавлен пакет selective-vpn-gui/controllers/ (core + views + domain mixin-модули);
    • selective-vpn-gui/dashboard_controller.py переведён в thin-facade с прежней точкой входа;
    • py_compile и импорты UI-модулей (vpn_dashboard_qt.py, traffic_mode_dialog.py, dns_benchmark_dialog.py) проходят.

4.3 api_client.py -> api/*

  • Разделение:
    • api/client.py (HTTP/SSE base + shared helpers)
    • api/models.py (dataclasses)
    • api/status.py, api/vpn.py, api/routes.py, api/traffic.py, api/dns.py, api/domains.py, api/trace.py
    • api/transport.py facade + api/transport_clients.py, api/transport_policy.py, api/transport_singbox.py
  • Сохраняется фасад ApiClient (старая точка импорта для UI).
  • Статус: выполнено (2026-03-10).
  • Что сделано:
    • добавлен пакет selective-vpn-gui/api/ с доменными mixin-модулями;
    • api_client.py переведён в backward-compatible facade (legacy imports сохранены);
    • api/client.py сокращён до base-слоя, доменные методы вынесены по подпапкам;
    • api/transport.py разрезан на subdomain-модули с сохранением класса TransportApiMixin.

5) План разрезания Go-ядра

5.1 transport_handlers.go -> app/transport_*

  • Разделение:
    • transport_handlers_clients.go (CRUD/lifecycle/health/metrics)
    • transport_handlers_policy.go (validate/apply/rollback/conflicts)
    • transport_validator.go (normalize + conflict detection)
    • transport_confirm_token.go (token lifecycle)
    • transport_state_store.go (load/save state/snapshots)
  • Сохраняем текущие endpoint-path и response-контракт без изменений.

5.2 server.go -> app/entrypoints.go + api_bootstrap.go + api_routes.go

  • Цель: развязать entrypoint-логику (Run*CLI), bootstrap API-сервера и registry маршрутов.
  • Статус: выполнено (2026-03-10).
  • Состав:
    • entrypoints.goRun, RunAPIServer, RunRoutesUpdateCLI, RunRoutesClearCLI, RunAutoloopCLI, legacy-dispatch;
    • api_bootstrap.go — bootstrap и lifecycle HTTP-сервера (runAPIServerAtAddr);
    • api_routes.go — thin-facade registerAPIRoutes;
    • api_routes_*.go — доменные registrars (core, traffic, transport, trace, dns, vpn) без изменения endpoint-path.

5.3 app/* -> подпакеты runtime (app/cli, app/bootstrap)

  • Цель: убрать "кучу" в корне app и перенести исполнимые runner-модули в отдельные папки, сохранив фасады в app.
  • Статус: выполнено (2026-03-10).
  • Состав:
    • app/cli/*routes-update, routes-clear, autoloop раннеры с dependency-injection (callback deps);
    • app/bootstrap/server_runner.go — единый HTTP server runner;
    • app/entrypoints.go и app/api_bootstrap.go оставлены thin-facade слоями.

5.4 transport_handlers.go -> модульные transport файлы

  • Цель: убрать крупнейший монолит transport control-plane без изменения endpoint-контракта.
  • Статус: выполнено (2026-03-10).
  • Состав:
    • transport_shared.go — state/version constants, mutex, общие типы;
    • transport_handlers_clients.go — clients CRUD/lifecycle/netns toggle handlers;
    • transport_handlers_policy.go — policy validate/apply/rollback/conflicts/capabilities handlers;
    • transport_policy_validate.go — normalize/validate/diff/conflict helpers;
    • transport_client_runtime.go — runtime/health/lifecycle/allocation helpers;
    • transport_tokens_state.go — confirm-token и state persistence.

5.5 Подпакеты transport (без циклических зависимостей)

  • Цель: выносить переиспользуемые части transport-логики в подпапки только там, где не возникает import-cycle с app.
  • Статус: in_progress (2026-03-10).
  • Уже вынесено:
    • app/transporttoken/store.go — confirm-token store (issue/consume/ttl cleanup) и token generator.
  • Дальше:
    • выделить в подпакеты часть stateless helper-функций (при сохранении фасадов в app).

6) Порядок выполнения (безопасный)

  1. api_client.py (минимальный риск для UI, проще ревьюить).
  2. dashboard_controller.py.
  3. vpn_dashboard_qt.py (таб за табом).
  4. transport_handlers.go в Go.

7) Definition of Done

  • Все текущие smoke/e2e проходят:
    • ./tests/run_all.sh
    • плюс ручная проверка пользователем в desktop приложении.
  • Нет изменений API-контракта (/api/v1/*) и event-kind.
  • В каждом крупном модуле остаётся читаемый размер (ориентир < 700 строк; предпочтительно < 500).

8) Дополнительно (после F1)

  • Добавить settings-механику видимости вкладок протоколов (SingBox, DNSTT, Phoenix) через QSettings/profile, чтобы включать только нужные модули UI.