Rapport d'Analyse de Code & Refactoring SRP (Juillet 2026)¶
Date : 3 juillet 2026 Statut : Résolu / Terminé
Ce rapport présente une analyse complète de la logique métier du codebase, en comptant et triant les lignes d'implémentation de chaque corps de fonction. Il met en lumière comment les fonctions monolithiques précédemment identifiées (qui violaient le principe de responsabilité unique ou SRP) ont été résolues, et explique les choix de conception structurelle tels que app_render_ui_trampoline.
📊 Métriques des fonctions du codebase (Après Refactoring)¶
En utilisant un parseur d'appariement d'accolades pour exclure les commentaires, les chaînes de caractères littérales et les définitions de macros, nous avons analysé les fichiers sources C dans le dossier src/. Voici la liste mise à jour des plus grandes fonctions, triées par ordre décroissant du nombre de lignes dans le corps de leur implémentation.
| Nom de la fonction | Fichier Source | Nombre de lignes | Plage de lignes | Notes / Statut |
|---|---|---|---|---|
postprocess_init |
src/postprocess_init.c |
150 | 171-320 | Refactorisé (Réduit depuis 229) |
app_draw_gamepad_help_overlay |
src/app_ui.c |
144 | 676-819 | Disposition de l'UI |
draw_help_overlay_keys |
src/app_ui.c |
139 | 836-974 | Disposition de l'UI |
billboard_sorter_sort_gpu |
src/billboard_sorter.c |
130 | 211-340 | Dispatch du compute shader GPU |
gpu_profiler_ui_draw |
src/gpu_profiler_ui.c |
129 | 223-351 | Disposition de l'UI |
app_run |
src/app.c |
127 | 219-345 | Refactorisé (Réduit depuis 207) |
postprocess_input_handle_key |
src/postprocess_input.c |
126 | 346-471 | Switch-case de mapping des entrées |
handle_preset_input |
src/postprocess_input.c |
124 | 144-267 | Refactorisé (Réduit depuis 210) |
handle_app_input |
src/app_input.c |
109 | 661-769 | Routage des entrées |
draw_debug_overlays |
src/billboard_renderer.c |
107 | 199-305 | Rendu de debug |
gpu_profiler_begin_frame |
src/gpu_profiler.c |
103 | 101-203 | Synchronisation des timestamps GPU |
postfx_final_composite |
src/postprocess_apply.c |
101 | 267-367 | Configuration de passe pipeline |
app_draw_help_overlay |
src/app_ui.c |
95 | 411-505 | Disposition de l'UI |
adaptive_sampler_should_sample |
src/adaptive_sampler.c |
88 | 101-188 | Logique du contrôleur |
billboard_sorter_sort_cpu_radix |
src/billboard_sorter.c |
88 | 421-508 | Implémentation du tri Radix |
light_probe_grid_render_debug |
src/light_probes.c |
88 | 677-764 | Rendu de debug |
compute_mean_luminance_gpu_start |
src/pbr.c |
85 | 284-368 | Dispatch PBO/GPU timing |
tracy_manager_async_transition |
src/tracy_manager.c |
85 | 142-226 | Transition de machine d'état |
fx_bloom_render |
src/effects/fx_bloom.c |
85 | 99-183 | Passe de rendu |
light_probe_worker |
src/light_probes.c |
84 | 345-428 | Mise à jour de sonde multithread |
postprocess_set_default_parameters |
src/postprocess_init.c |
84 | 84-167 | Nouvel assistant statique |
ubo_full_rebuild |
src/postprocess_apply.c |
82 | 161-242 | Compactage des données |
log_ascii_timeline |
src/app_metrics.c |
82 | 131-212 | Outils de journalisation texte |
renderer_draw_frame |
src/renderer.c |
82 | 27-108 | Configuration frame bas niveau |
light_probe_grid_sync |
src/light_probes.c |
81 | 544-624 | Synchronisation/upload de buffer |
app_handle_env_input |
src/app_input.c |
81 | 105-185 | Logique de callback d'entrées |
integrate_step |
src/nbody/nbody_physics.c |
81 | 64-144 | Étape de physique |
(Note : scene_render a été réduite de 203 lignes à seulement 61 lignes propres, la retirant ainsi complètement de la liste des fonctions volumineuses)
🔍 Résolution des fonctions monolithiques (Audit SRP)¶
Nous avons complété une refactorisation SRP complète sur les quatre fonctions ciblées. Voici le résumé des problèmes résolus :
1. app_run (src/app.c)¶
- Avant (207 lignes) : Gérait la boucle d'événements GLFW, la mise à jour des timers, la mise à jour de la caméra (clavier / manettes), la détection de changement de subdivisions de l'icosphere et la régénération de son maillage.
- Après (127 lignes) : Uniquement le moteur de la boucle principale de l'application.
- La logique d'actualisation de la caméra a été extraite dans
static void app_update_camera(App* app). - La détection de modification des subdivisions et la régénération du maillage ont été extraites dans
static void app_update_mesh_subdivisions(App* app, int* last_subdiv).
- La logique d'actualisation de la caméra a été extraite dans
2. postprocess_init (src/postprocess_init.c)¶
- Avant (229 lignes) : Mélangeait la configuration statique des presets d'effets, la création de l'UBO de paramètres, l'allocation des PBOs d'exposition, l'allocation du buffer d'histogramme et la compilation de shaders.
- Après (150 lignes) : Se consacre exclusivement à la création des ressources OpenGL et à l'initialisation des sous-systèmes.
- L'initialisation des paramètres et presets par défaut a été déportée dans
static void postprocess_set_default_parameters(PostProcess* post_processing).
- L'initialisation des paramètres et presets par défaut a été déportée dans
3. scene_render (src/scene_render.c)¶
- Avant (203 lignes) : Préparait les paramètres de dessin de la frame, rendait la skybox, configurait le tri des billboards transparents, dessinait la géométrie et orchestrait les VFX de traînées de particules et d'ondes de choc.
- Après (61 lignes) : Orchestrateur de rendu de haut niveau très court et lisible.
- Le rendu de la skybox a été extrait dans
static void scene_render_skybox_pass(Scene* scene, GPUProfiler* profiler, mat4 inv_view_proj). - La préparation et le rendu des billboards transparents ont été extraits dans
static void scene_render_billboards_pass(Scene* scene, GPUProfiler* profiler, mat4 view, mat4 proj, mat4 previous_view_proj, vec3 camera_pos, int width, int height). - Le rendu des traînées N-body et ondes de choc a été extrait dans
static void scene_render_vfx_pass(Scene* scene, GPUProfiler* profiler, mat4 view, mat4 proj, vec3 camera_pos, int width, int height).
- Le rendu de la skybox a été extrait dans
4. handle_preset_input (src/postprocess_input.c)¶
- Avant (210 lignes) : Switch-case mappant les touches de raccourcis d'effets, avec des boucles de cyclage complexes pour les LUTs 3D et le banding d'images.
- Après (124 lignes) : Table de routage clavier simplifiée.
- Le cyclage du mode de banding a été extrait dans
static void cycle_banding_styles(const PostProcessInputContext* ctx). - Le chargement et cyclage des LUTs a été extrait dans
static void cycle_lut_styles(const PostProcessInputContext* ctx, int mods).
- Le cyclage du mode de banding a été extrait dans
🔀 Le rôle de app_render_ui_trampoline¶
Dans src/app.c, la fonction adaptatrice suivante est conservée :
Pourquoi existe-t-il ?¶
Cette fonction est un adaptateur de type face à l'effacement de type (Type Erasure Trampoline / Design Pattern Adapter) conçu pour assurer la séparation des préoccupations (SoC) et empêcher les dépendances circulaires.
graph TD
App[app.c / app.h <br/><i>Orchestrateur de haut niveau</i>]
Renderer[renderer.c / renderer.h <br/><i>Pipeline de rendu bas niveau</i>]
AppUI[app_ui.c / app_ui.h <br/><i>Interface Dear ImGui</i>]
App -->|inclut| Renderer
App -->|inclut| AppUI
AppUI -->|prend const App*| App
Renderer -.->|Rappel via RenderUIFn| App
style Renderer fill:#1a1b26,stroke:#f7768e,stroke-width:2px;
style App fill:#1a1b26,stroke:#7aa2f7,stroke-width:2px;
- Prévention des Dépendances Circulaires :
app.ccontrôle la boucle d'exécution et doit appelerrenderer_draw_frame(défini dansrenderer.h).app.cdépend donc derenderer.h.- Si le module
rendererappelait directementapp_render_ui(const App* app), il devrait connaître la définition de la structureApp, obligeantrenderer.hà inclureapp.h. - Cela créerait une dépendance circulaire :
app.h🔁renderer.h, violant les règles d'architecture en couches.
- Découplage de Contexte :
- Pour garder le code de rendu bas niveau totalement déconnecté des structures applicatives,
renderer.hdéfinit une signature générique de callback : - Le renderer appelle ce callback au moment opportun sans rien savoir de qui dessine l'interface ni de quelle structure lui est transmise.
- Pour garder le code de rendu bas niveau totalement déconnecté des structures applicatives,
- Encapsulation Typée :
- La fonction de dessin de l'interface utilisateur concrète est
void app_render_ui(const App* app). - Puisque cette fonction attend un
const App*et non unvoid*, la passer directement au renderer générerait des avertissements de compilation ou nécessiterait des casts risqués. - La fonction adaptatrice
app_render_ui_trampolineaccepte levoid* user_dataattendu par le renderer, effectue le cast interne proprement versconst App*et appelleapp_render_ui.
- La fonction de dessin de l'interface utilisateur concrète est