Files
fn_registry/dev/issues/completed/0041-cpp-app-best-practices.md
T

141 lines
5.2 KiB
Markdown

---
id: "0041"
title: "C++ app shell estandarizado: BEST_PRACTICES + AppConfig extendido"
status: completado
type: feature
domain:
- cpp-stack
scope: app-scoped
priority: alta
depends: []
blocks: []
related: []
created: 2026-05-17
updated: 2026-05-17
tags: []
---
# 0041 — C++ app shell estandarizado: BEST_PRACTICES + AppConfig extendido
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | 0041 |
| **Estado** | pendiente |
| **Prioridad** | alta |
| **Tipo** | feature — C++ framework (`cpp/framework/`) + docs |
## Dependencias
Ninguna. Habilita **0043** (estandarizar apps existentes) y todo desarrollo futuro de apps C++.
---
## Objetivo
1. Documentar el patron canonico de apps C++ del registry en `cpp/PATTERNS.md` con checklist obligatorio.
2. Extender `fn::AppConfig` para que `fn::run_app()` registre About + paneles + theming en una sola llamada, eliminando boilerplate por app.
## Contexto
La auditoria muestra que `chart_demo`, `primitives_gallery`, `shaders_lab` y `registry_dashboard` arrancan distinto: solo `shaders_lab` aprovecha `app_menubar` con paneles, solo `registry_dashboard` registra About + Settings, `primitives_gallery` llama `apply_dark_theme()` + `gl_loader_init()` a mano que el resto delega a `run_app()`. Sin estandar, cada app proxima reinventa esto.
## Arquitectura
```
cpp/
├── PATTERNS.md # NEW — checklist y patrones
├── framework/
│ ├── app_base.h # MOD — extender AppConfig
│ └── app_base.cpp # MOD — aplicar nuevos campos
└── functions/core/
└── (sin cambios — app_menubar/app_about/app_settings ya existen)
```
### AppConfig extendido (propuesta)
```cpp
struct AppAboutInfo {
const char* name = nullptr;
const char* version = nullptr;
const char* description = nullptr;
};
struct AppConfig {
const char* title = "fn app";
int width = 1280;
int height = 800;
bool vsync = true;
bool viewports = false;
ThemeMode theme = ThemeMode::FnDark;
float bg_r=0,bg_g=0,bg_b=0;
// NEW — registra About si name != nullptr.
AppAboutInfo about{};
// NEW — paneles toggleables del menubar (si != nullptr).
const fn_ui::PanelToggle* panels = nullptr;
size_t panel_count = 0;
// NEW — callbacks de layouts persistentes (si != nullptr).
fn_ui::LayoutCallbacks* layouts_cb = nullptr;
// NEW — si true, llama gl_loader_init() antes del primer frame.
bool init_gl_loader = false;
};
```
`run_app()` aplica:
- Si `about.name != nullptr``fn_ui::about_window_set_info(...)`.
- Si `init_gl_loader``fn::gfx::gl_loader_init()` tras crear el contexto GL.
- Cada frame, si `panels != nullptr` o `layouts_cb != nullptr`, llama `app_menubar(panels, panel_count, layouts_cb)` automaticamente — la app NO la llama.
## Tareas
### Fase 1 — Doc
1.1 Crear `cpp/PATTERNS.md` con checklist:
- Usa `fn::run_app()` con `AppConfig` (jamas `glfwInit` directo).
- Registra About via `AppConfig::about` o `about_window_set_info()`.
- Registra Settings extras via `settings_window_add_section()`.
- Si tienes paneles, define `static constexpr fn_ui::PanelToggle panels[]` y pasalo en `AppConfig::panels`.
- Si necesitas layouts, implementa `LayoutCallbacks` y pasalas en `AppConfig::layouts_cb`.
- Usa `fn_tokens::colors|spacing|radius` siempre. Nunca colores hex literales.
- Evita `ImGui::BeginTable / Selectable / BeginPopupModal / BeginChild` con styling manual — usa `dashboard_grid`, `tree_view`/`select`, `modal_dialog`, `dashboard_panel`.
### Fase 2 — Framework
2.1 Anadir campos `about`, `panels`, `panel_count`, `layouts_cb`, `init_gl_loader` a `AppConfig` en `app_base.h`.
2.2 En `run_app()` (`app_base.cpp`):
- Tras `gl_loader_init` opcional.
- Tras `about_window_set_info` si procede.
- Antes del `render_fn()` por frame, llama `app_menubar(panels, panel_count, layouts_cb)` si alguno != nullptr.
2.3 Backward-compat: campos nuevos opcionales con defaults — apps existentes compilan sin tocarlas.
### Fase 3 — Validacion
3.1 Compilar todas las apps existentes sin cambios, verificar que no rompe.
3.2 Build Linux + cross-compile Windows.
### Fase 4 — Indexar
4.1 `./fn index` para refrescar metadata (no cambia funciones — solo doc).
## Decisiones de diseno
- `AppConfig` con campos opcionales (no nuevos overloads de `run_app`) — minimiza la API surface.
- La menubar se llama desde `run_app` solo si la app declara paneles/layouts; en otro caso la app puede llamar `app_menubar(nullptr,0,nullptr)` ella misma (compat).
## Riesgos
- Apps que ya llaman `app_menubar` manualmente con `panels` distintos al `AppConfig`: documentar — `run_app` la llama una vez al inicio del frame, la app puede dejar de hacerlo.
## Validacion
- `cpp/PATTERNS.md` legible en GitHub.
- `chart_demo` (la mas simple) puede ahora declararse asi:
```cpp
fn::run_app({.title="chart demo", .about={.name="chart demo", .version="0.1", .description="..."}}, render);
```
- Tests de compilacion OK para shaders_lab/chart_demo/primitives_gallery/registry_dashboard sin modificar.