Files
fn_registry/dev/issues/completed/0045-cpp-extract-pure-logic.md
T
2026-04-28 23:59:08 +02:00

4.5 KiB

0045 — Extraer logica pura de componentes C++ impuros (sql_workbench, process_runner, file_watcher)

Metadata

Campo Valor
ID 0045
Estado pendiente
Prioridad media
Tipo refactor — cpp/functions/core

Dependencias

Ninguna.


Objetivo

Extraer la parte pura (parsing, state machines, diff) de componentes hoy mezclados con I/O y UI. Resultado: cada uno se descompone en <x>_pure_cpp_core (testeable, sin ImGui ni I/O) + <x>_ui_cpp_core (thin wrapper impuro). Tambien aplica al compiler de shaders_lab que vive en su main.cpp.

Contexto

  • sql_workbench_cpp_core mezcla parsing SQL, ejecucion SQLite y render ImGui en una sola funcion.
  • process_runner_cpp_core mezcla state machine de proceso (idle/running/success/error) con UI helpers.
  • file_watcher_cpp_core mezcla polling de filesystem con notificaciones UI.
  • shaders_lab/main.cpp tiene compile_code(), compile_dag(), mark_code_dirty() inline.

Sin separacion no hay tests unitarios, no es reutilizable y crece la deuda con cada feature.

Arquitectura

cpp/functions/core/
├── sql_parse.{h,cpp,md}                     # NEW — pure
├── sql_workbench.{h,cpp,md}                 # MOD — thin wrapper, llama sql_parse
├── process_state_machine.{h,cpp,md}         # NEW — pure (transiciones)
├── process_runner.{h,cpp,md}                # MOD — usa process_state_machine
├── file_poll_diff.{h,cpp,md}                # NEW — pure (calcula diff de snapshots)
└── file_watcher.{h,cpp,md}                  # MOD — usa file_poll_diff

cpp/apps/shaders_lab/
├── compiler.h                               # NEW
├── compiler.cpp                             # NEW (extrae compile_code/compile_dag)
└── main.cpp                                 # MOD (461 → ~250 lineas)

Tareas

Fase 1 — sql_workbench

1.1 sql_parse_cpp_core (pure): tokeniza SQL minimal (separa statements por ;, detecta keyword inicial: SELECT/INSERT/UPDATE/DELETE/CREATE/etc., devuelve struct SqlStatement{kind, text, line}). 1.2 sql_workbench pasa a llamar sql_parse para detectar tipo de statement antes de ejecutar; el parser puro es testeable sin SQLite. 1.3 Test unitario: dado SQL multi-statement, devuelve N statements con kind correcto.

Fase 2 — process_runner

2.1 process_state_machine_cpp_core (pure): funcion process_transition(current_state, event) -> new_state con eventos {Trigger, Spawned, Finished, Failed, Timeout} y estados {Idle, Running, Success, Error}. 2.2 process_runner pasa a usar la maquina pura para gestionar transiciones; la parte impura solo dispara popen/spawn/wait y traduce a eventos. 2.3 Test unitario: secuencia de eventos → estado final esperado.

Fase 3 — file_watcher

3.1 file_poll_diff_cpp_core (pure): dado dos snapshots vector<FileEntry{path, size, mtime}>, devuelve FileDiff{added, modified, removed}. 3.2 file_watcher pasa a hacer el polling impuro y delegar el diff al puro. 3.3 Test unitario: dado A=[a,b,c], B=[a,b',d] → modified=[b], added=[d], removed=[c].

Fase 4 — shaders_lab compiler

4.1 Crear cpp/apps/shaders_lab/compiler.{h,cpp} con compile_code(code, &out_log) -> bool, compile_dag(...), mark_code_dirty(...). Estas funciones llaman al backend GLSL existente — no son del registry porque dependen de estado interno de shaders_lab. 4.2 Mover el codigo correspondiente desde main.cpp. 4.3 main.cpp queda <250 lineas.

Fase 5 — Indexar y validar

5.1 ./fn index para registrar las 3 nuevas funciones puras. 5.2 Verificar purity: pure, returns_optional: false, error_type: "" en cada una. 5.3 Build Linux + Windows. Tests pasan.

Decisiones

  • sql_parse es deliberadamente minimal — no es un parser SQL completo, solo distingue tipos de statement. Si en el futuro hace falta mas, se anade.
  • compile_code/compile_dag quedan como utilities de la app, NO en el registry (dependen de tipos internos de shaders_lab).

Riesgos

  • Tests unitarios C++: no hay framework configurado todavia (issue 0047 lo monta). Mientras tanto, anadir tests dentro del archivo via #ifdef TESTING + un main pequeno, o esperar a 0047.
  • Decision: usar #ifdef TESTING por ahora; cuando 0047 monte Catch2, migrar.

Validacion

./fn run sql_parse_cpp_core         # ejecuta el test si lo hay
./fn show sql_parse_cpp_core
./fn show process_state_machine_cpp_core
./fn show file_poll_diff_cpp_core
cmake --build cpp/build --target shaders_lab