← Volver al Portfolio
Análisis Estático

MasbitsEngine CodeGraph Analysis

Análisis profundo de arquitectura de motor de juego en C++ con 29,785 símbolos (27,580 líneas), 989 funciones analizadas: complejidad, acoplamiento modular, código muerto y recomendaciones de refactorización.

1. Executive Summary

MasbitsEngine es un motor de juego en C++ con renderer Vulkan que sirve como proyecto central del portfolio. Este análisis estático fue realizado con CodeGraph (AST analysis con Louvain community detection), Daem0n MCP y Engram para evaluar la salud arquitectural del código. 989 funciones analizadas de 29,785 símbolos totales, con corrección por falsos positivos de código condicional #if EDITOR / #if ENGINE.

Código Métricas

29,785
Símbolos Totales
27,580
Total Lines
118
Clases
172
Structs
78
Namespaces
~1,001
Métodos
989
Funciones Analizadas

Breakdown por Lenguaje

Lenguaje Extensión Líneas Porcentaje
C++ .cpp 17,553 63.7%
C++ .hpp 9,823 35.6%
C++ .h 204 0.7%
Total C++ 27,580 100%

2. Top 5 by Cyclomatic Complexity

# Función Archivo Cicl. Cogn. MI Líneas
1 EditorActions::executeEditorActions src/Editor/Manager/editorActions.cpp:284 58 332 22.9 373
2 CVulkanRenderImpl::handleMousePicking src/RenderCore/Renderer/renderer.cpp:1315 54 88 32.4 222
3 TilePreviewDialog::renderView src/Editor/Data/TilePreviewDialog.cpp:1088 53 163 30.6 273
4 TilesetGenerationDialog::renderView src/Editor/Data/TilesetGenerationDialog.cpp:1002 53 163 30.6 287
5 TilesetGenerationDialog::renderGridPreview src/Editor/Data/TilesetGenerationDialog.cpp:1905 49 117 31.8 287

3. Module Coupling & Fragmentation

El análisis Louvain community detection reveló que módulos con alto número de comunidades están fragmentados — indicando architectural drift. Cada comunidad representa una agrupación natural de código que debería corresponder a una responsabilidad cohesiva.

Módulo Comunidades Interpretación
RenderCore/BaseRender 19 Muy fragmentado — múltiples responsabilidades mezcladas
Game/Player/AnimStates 18 Alta fragmentación — estados de animación dispersos
Game/Components 16 Fragmentado — componentes con responsabilidades cruzadas
Editor/Data 15 Considerable — editor y gestión de datos acoplados
RenderCore/Renderer 14 Significativo — renderer con múltiples sub-responsabilidades
1,441 Archivos
60,159 Nodos AST
5,399 Aristas
43 Drift Score

High community count indica que el código se agrupa naturalmente en muchas comunidades pequeñas en lugar de pocas comunidades grandes y cohesivas. Esto es un síntoma de architectural drift — el código ha evolucionado hacia múltiples responsabilidades dentro de lo que deberían ser módulos con fronteras claras.

4. Refactoring Candidates

Funciones que superan umbrales de complejidad y tienen alto riesgo de bugs. Corregidas las clasificaciones de dead-ffi que no consideraban código dentro de bloques #if condicionales.

Función Cognitiva MI Llaman Estado Real
EditorActions::executeEditorActions 332 22.9 Sí (appEngineTraits.cpp:63, 100) #if EDITOR — CodeGraph marcó falso dead-ffi
loadLevelFromFile 187 13.6 Sí (editormanager.cpp:113, gamemanager.cpp:50) Falso dead-ffi — llamada desde ambos modos
CVulkanRenderImpl::handleMousePicking 88 32.4 Interna renderer.cpp — complejidad alta inherente al Vulkan
CVulkanRenderImpl::buildCommandBuffers 110 22.6 Interna 456 líneas, nesting 6
TilePreviewDialog::renderView 163 30.6 Interna #if EDITOR — falso dead-ffi

🔴 Prioridad Alta: executeEditorActions

373 líneas, nesting depth 12, MI 22.9 (crítico). Esta función fue clasificada como dead-ffi por CodeGraph, pero está llamada desde appEngineTraits.cpp:63 y :100 dentro de bloques #if EDITOR. Recomendación: extraer cada caso del switch en su propia función policy-driven, reducir nesting con early returns, y verificar callers dentro de bloques condicionales.

🟠 Prioridad Alta: loadLevelFromFile

MI 13.6 (crítico). Clasificada como dead-ffi pero llamada desde editormanager.cpp:113 y gamemanager.cpp:50 — existe en ambos modos de compilación. Recomendación: separar parsers por formato en funciones dedicadas, aplicar Strategy pattern para cada tipo de nivel.

5. Methodology & Tools

Técnicas de Análisis

Louvain Community Detection

Algoritmo de detección de comunidades en grafos que agrupa nodos densamente conectados. Usado para identificar módulos naturales del código y medir fragmentation. Un alto número de comunidades por módulo indica architectural drift.

CFG (Control Flow Graph) Analysis

Modela las rutas de ejecución dentro de cada función. Permite calcular cyclomatic complexity (# rutas independientes) y cognitive complexity (# decisiones anidadas que el cerebro humano debe rastrear).

Dead Code Detection (dead-ffi)

Clasificación de funciones como dead-ffi (Foreign Function Interface) — funciones que no tienen callers en el grafo de llamadas. Indica código muerto o funciones de API no utilizadas actualmente.

Data Flow Analysis

rastreo de cómo fluyen los datos entre funciones a través de parámetros y valores de retorno. Permite calcular el blast radius de cambios y dependencies transitivas.

Herramientas Utilizadas

Análisis AST con Louvain community detection, CFG analysis, dead-ffi classification, data flow edges y impact analysis

AI memory system con persistent context, outcome tracking y semantic search para decisiones arquitecturales previas

Persistent memory capture for technical decisions, bug fixes y patterns established during the analysis

Knowledge base con historical context sobre evolutions del proyecto y trade-offs arquitecturales previos

Herramienta Propósito
CodeGraph
Daem0n MCP
Engram
OpenLore

Métricas Explicadas

Cognitive Complexity

Puntuación de cuan difícil es seguir mentalmente el código. Penaliza anidación (+1 por nivel) y saltos lógicos (+1 por if/else/for/while). A diferencia del cyclomatic, crece con la profundidad de anidación. Threshold de warning: 15.

Cyclomatic Complexity

Número de caminos de ejecución independientes en una función. Se calcula como E - N + 2P (edges - nodes + 2*connected components). Threshold de warning: 10. No penaliza anidación directamente.

Maintainability Index (MI)

Puntuación 0-100 que combina cyclomatic complexity, lines of code y cyclomatic per LOC. Valores >20 indican código difícil de mantener. 20-25 = crítico, 25-40 = alto riesgo, >40 = aceptable. Threshold de warning: 20.

6. CodeGraph Limitations — Conditional Compilation False Negatives

CodeGraph lee archivos fuente directamente sin ejecutar el preprocesador C++ (#if, #ifdef, #endif). Esto causa falsos negativos en la detección de código muerto: funciones llamadas solo dentro de bloques condicionales se clasifican como dead-ffi o dead-leaf aunque existen en el códigobase.

5 Requirements
6 Scenarios
1 Daem0n Rule (ID 1)
1.5x Boost a enfoques fallidos

Mecanismo del Error

Paso Lo que hace CodeGraph Resultado
1. Lectura de fuente Lee appEngineTraits.cpp directamente Sin evaluar #if EDITOR
2. AST vacío Funciones dentro del #if no tienen callers 0 callers detectados
3. Clasificación Sin callers → dead-ffi dead-ffi (falso positivo)
4. Verificación grep -r "func" --include="*.cpp" encuentra llamadas dentro de #if EDITOR Código es vivo, no muerto

Ejemplo Real

Función Archivo Clasificación CodeGraph Realidad
AppEngine::OnEvent appEngineTraits.cpp:63 dead-ffi Callada dentro de #if EDITOR — código vivo
AppEngine::Run appEngineTraits.cpp:100 dead-ffi Callada dentro de #if EDITOR — código vivo

Comandos Afectados

Patrón de Verificación

Regla Daem0n ID 1: Cuando CodeGraph clasifique una función C++ como dead-ffi, ejecutar grep -r "function_name" --include="*.cpp" --include="*.h" --include="*.hpp" --include="*.inl" antes de concluir que el código es no utilizado. Si grep encuentra llamadas dentro de bloques #if, el código es vivo en ese modo de compilación.

Las aproximaciones fallidas reciben 1.5x boost en búsquedas futuras de Daem0n para evitar repetir enfoques que ya demostraron no funcionar con código condicional.