← Volver al Portfolio
Análisis Estático

Análisis CodeGraph de MasbitsEngine

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

1. Resumen Ejecutivo

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 (análisis AST 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.

Métricas del Código

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

Desglose 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 por Complejidad Ciclomática

# 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. Acoplamiento y Fragmentación de Módulos

El análisis Louvain community detection reveló que los módulos con un alto número de comunidades están fragmentados, lo que indica architectural drift (desviación arquitectural). 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 Puntaje Drift

Alto número de comunidades 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 (desviación arquitectural): el código ha evolucionado hacia múltiples responsabilidades dentro de lo que deberían ser módulos con fronteras claras.

4. Candidatos a Refactorización

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. Metodología y Herramientas

Técnicas de Análisis

Detección de Comunidades Louvain

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

Análisis de Grafos de Flujo de Control (CFG)

Modela las rutas de ejecución dentro de cada función. Permite calcular la complejidad ciclomática (# de rutas independientes) y la complejidad cognitiva (# de decisiones anidadas que el cerebro humano debe rastrear).

Detección de Código Muerto (dead-ffi)

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

Análisis de Flujo de Datos

Rastreo de cómo fluyen los datos entre funciones a través de parámetros y valores de retorno. Permite calcular el blast radius (radio de impacto) de cambios y las dependencias transitivas.

Herramientas Utilizadas

Herramienta Propósito
CodeGraph Análisis AST con Louvain community detection, CFG analysis, dead-ffi classification, data flow edges y impact analysis
Daem0n MCP AI memory system con persistent context, outcome tracking y semantic search para decisiones arquitecturales previas
Engram Captura de memoria persistente para decisiones técnicas, corrección de errores y patrones establecidos durante el análisis
OpenLore Base de conocimientos con contexto histórico sobre las evoluciones del proyecto y los trade-offs arquitecturales previos

Métricas Explicadas

Complejidad Cognitiva

Puntuación de qué tan difícil es seguir mentalmente el código. Penaliza la anidación (+1 por nivel) y los saltos lógicos (+1 por if/else/for/while). A diferencia de la ciclomática, crece con la profundidad de anidación. Umbral de advertencia: 15.

Complejidad Ciclomática

Número de caminos de ejecución independientes en una función. Se calcula como E - N + 2P (aristas - nodos + 2*componentes conectadas). Umbral de advertencia: 10. No penaliza la anidación directamente.

Índice de Mantenibilidad (MI)

Puntuación de 0 a 100 que combina la complejidad ciclomática, el número de líneas de código y la ciclomática por LOC. Valores >20 indican código difícil de mantener. 20-25 = crítico, 25-40 = alto riesgo, >40 = aceptable. Umbral de advertencia: 20.

6. Limitaciones de CodeGraph — Falsos Negativos por Compilación Condicional

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 Requisitos
6 Escenarios
1 Regla Daem0n (ID 1)
1.5x Prioridad 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 llamadores 0 llamadores detectados
3. Clasificación Sin llamadores → 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.

Los enfoques fallidos reciben una prioridad 1.5x mayor en búsquedas futuras de Daem0n para evitar repetir métodos que ya demostraron no funcionar con código condicional.

7. Verificacion de Syntax Highlighting Global

Esta seccion demuestra que el highlighting de Everforest Dark funciona en cualquier pagina del sitio, no solo en blog posts. El siguiente bloque de codigo C++ fue procesado por Shiki via el modulo compartido src/lib/highlighter.ts:

#include <iostream>

int main() {
    std::cout << "Hello, Everforest!" << std::endl;
    return 0;
}

Si ves colores Everforest Dark en este bloque (comentarios en verde claro, strings en amarillo, keywords en rojo), el highlighting esta funcionando correctamente en paginas no-blog.