Skip to content

05_00_02_dependency_tracker - El Guardián de Relaciones

📊 Descripción

El Dependency Tracker gestiona el grafo dirigido acíclico (DAG) de dependencias entre módulos DSP, garantizando que no existan ciclos y que se respete la jerarquía L0→L1→L2→L3.

🎯 Capacidades

✅ Algoritmos Implementados

  1. Cycle Detection - DFS con 3 colores (WHITE/GRAY/BLACK)
  2. Topological Sort - Algoritmo de Kahn
  3. Transitive Closure - Dependencias recursivas completas
  4. Reverse Dependencies - Quién depende de qué
  5. Hierarchy Validation - Enforce L0→L1→L2→L3

🔍 Validaciones Automáticas

  • ✅ No ciclos de dependencias
  • ✅ No auto-dependencias (módulo no puede depender de sí mismo)
  • ✅ Jerarquía respetada (L0 no depende de nadie, L1 solo de L0, etc.)
  • ✅ No huérfanos (dependencias apuntan a módulos existentes)

🚀 Uso

API Python

from dependency_graph import DependencyGraph

# Crear grafo
graph = DependencyGraph()

# Registrar módulos
graph.add_module("add_kernel", "L0_KERNEL", "1.0.0")
graph.add_module("svf_filter", "L1_ATOM", "2.0.0")
graph.add_module("synth_voice", "L2_CELL", "1.0.0")

# Añadir dependencias
graph.add_dependency("svf_filter", "add_kernel", "^1.0.0")
graph.add_dependency("synth_voice", "svf_filter", "^2.0.0")

# Validar grafo
errors = graph.validate()
if errors:
    for err in errors:
        print(f"Error: {err.message}")

# Obtener orden de compilación
build_order = graph.topological_sort()
print(f"Build order: {build_order}")

# Dependencias de un módulo
deps = graph.get_dependencies("synth_voice", recursive=True)
print(f"All dependencies: {deps}")

# Quién depende de un módulo
rev_deps = graph.get_reverse_dependencies("svf_filter")
print(f"Modules depending on svf_filter: {rev_deps}")

Integración con Database

from dependency_manager import DependencyManager
from registry_db import RegistryDatabase

# Conectar a database
db = RegistryDatabase(Path('registry.db'))
db.connect()

# Crear manager (auto-construye grafo desde DB)
manager = DependencyManager(db)

# Validar todo
errors = manager.validate_all()

# Obtener orden de compilación
build_order = manager.get_build_order()

# Análisis de impacto
impact = manager.get_impact_analysis('svf_filter')
print(f"Direct dependents: {impact['direct']}")
print(f"Transitive dependents: {impact['transitive']}")

# Sugerir orden de tests
changed = ['svf_filter', 'oscillator']
test_order = manager.suggest_test_order(changed)
print(f"Test these modules in order: {test_order}")

CLI Usage

# Validar todas las dependencias
python dependency_manager.py --db registry.db --validate

# Mostrar orden de compilación
python dependency_manager.py --db registry.db --build-order

# Análisis de impacto
python dependency_manager.py --db registry.db --impact svf_filter

# Exportar a Graphviz DOT
python dependency_manager.py --db registry.db --export-dot deps.dot

# Generar imagen del grafo
dot -Tpng deps.dot -o dependencies.png

📐 Algoritmos Detallados

1. Cycle Detection (DFS con Colores)

WHITE: Nodo no visitado
GRAY:  Nodo siendo procesado (en stack DFS)
BLACK: Nodo completamente procesado

Si encontramos arista a nodo GRAY → ¡Ciclo detectado!

Complejidad: O(V + E)

2. Topological Sort (Kahn's Algorithm)

1. Calcular in-degree de cada nodo
2. Queue = nodos con in-degree 0
3. Mientras queue no vacía:
   - Pop nodo N
   - Añadir N a resultado
   - Decrementar in-degree de vecinos
   - Si in-degree == 0 → añadir a queue
4. Si resultado.length != total_nodes → ¡Tiene ciclos!

Complejidad: O(V + E)

3. Transitive Closure

Calcula todas las dependencias recursivas usando DFS:

visited = {}
stack = [start]
while stack:
    current = pop(stack)
    for dependency in current.dependencies:
        if not visited[dependency]:
            stack.push(dependency)
            visited[dependency] = true

Complejidad: O(V + E)

🏗️ Jerarquía de Niveles

L0_KERNEL  → No puede depender de NADIE
L1_ATOM    → Solo puede depender de L0
L2_CELL    → Puede depender de L0, L1
L3_ENGINE  → Puede depender de L0, L1, L2

Razón: Garantiza que kernels sean independientes y que la arquitectura sea ordenada de abajo hacia arriba.

📊 Visualización con Graphviz

El grafo se puede exportar a formato DOT:

# Exportar
python dependency_manager.py --db registry.db --export-dot deps.dot

# Generar PNG
dot -Tpng deps.dot -o deps.png

# Generar SVG (escalable)
dot -Tsvg deps.dot -o deps.svg

# Generar PDF
dot -Tpdf deps.dot -o deps.pdf

Colores por nivel: - L0_KERNEL: 🔴 Rojo (#ff6b6b) - L1_ATOM: 🔵 Cyan (#4ecdc4) - L2_CELL: 🟦 Azul (#45b7d1) - L3_ENGINE: 🟢 Verde (#96ceb4)

Estilos de aristas: - Sólida: Dependencia obligatoria - Dashed: Dependencia opcional

🔥 Casos de Uso

Caso 1: Detectar ciclo antes de añadir dependencia

try:
    graph.add_dependency("module_a", "module_b", "^1.0.0")
except ValueError as e:
    print(f"Rejected: {e}")
    # "Adding dependency module_a → module_b would create a cycle"

Caso 2: Análisis de impacto antes de breaking change

# Antes de lanzar svf_filter v3.0.0 con breaking changes
impact = manager.get_impact_analysis('svf_filter')

print(f"Breaking change afectará a:")
print(f"  - {len(impact['direct'])} módulos directamente")
print(f"  - {len(impact['transitive'])} módulos transitivamente")

# Planificar migration guide para todos los afectados

Caso 3: Orden de tests en CI/CD

# Detectar qué cambió en este PR
changed_modules = git_diff_modules()

# Calcular qué debe testearse
test_order = manager.suggest_test_order(changed_modules)

# Ejecutar tests en orden correcto
for module in test_order:
    run_tests(module)

Caso 4: Build system integration

# Obtener orden de compilación
build_order = manager.get_build_order()

# Compilar en orden correcto
for module in build_order:
    compile(module)

⚠️ Limitaciones Actuales

  1. Version constraint checking: Actualmente no valida semver constraints (^1.0.0, >=2.0.0). Solo almacena el string.
  2. Optional dependencies: Se rastrean pero no hay lógica especial para builds condicionales.
  3. Performance: Grafo se reconstruye completo desde DB. Para repos grandes (10,000+ módulos), considerar incremental updates.

📦 Dependencias

Ninguna externa - solo stdlib Python 3.7+

🎯 Próximas Mejoras

  • Semver constraint validation con librería semver
  • Incremental graph updates (no rebuild completo)
  • Support para "provides" virtual modules
  • Dependency conflicts resolution
  • Visualization interactiva (web UI)

Status: ✅ Funcional y listo para uso Tested: ✅ Algoritmos validados con ejemplos Coverage: ⚠️ Pendiente tests unitarios formales