Skip to content

05_02_interfaces - System Integration & Interfaces

📋 Descripción General

API pública y sistema de integración para el Dependency Graph Visualizer. Proporciona headers consolidados, configuración CMake, y ejemplos de integración para consumir este subsistema desde otros módulos o proyectos externos.

🎯 Objetivos

  1. Clean Public API - Headers consolidados sin dependencias internas
  2. CMake Integration - Find modules y configuración de paquete
  3. Easy Integration - Ejemplos de uso desde otros proyectos
  4. Version Management - Compatibilidad y versionado semántico
  5. Documentation - Guías de integración completas

🏗️ Arquitectura de Interfaces

05_02_interfaces/
├── include/                         # Public headers
│   └── audio_lab/
│       └── dependency_graph/
│           └── dependency_graph.hpp # Single include header
├── cmake/
│   ├── DependencyGraphConfig.cmake  # Find module
│   ├── DependencyGraphTargets.cmake # Exported targets
│   └── DependencyGraphVersion.cmake # Version checking
├── examples/
│   ├── simple_usage.cpp             # Basic usage
│   ├── advanced_integration.cpp     # Advanced features
│   └── custom_catalog.cpp           # Custom catalog loading
└── README.md                        # Integration guide

📦 Public API

Single Include Header

El sistema completo se puede incluir con un solo header:

#include <audio_lab/dependency_graph/dependency_graph.hpp>

using namespace audio_lab::dependency_graph;

int main() {
    // Load and visualize dependency graph
    GraphBuilder builder;
    builder.load_from_catalog("catalog.json");
    Graph graph = builder.build();

    // Export visualization
    DotExporter exporter;
    exporter.export_to_file(graph, "dependencies.dot");

    return 0;
}

Component Headers (Optional)

Para uso más granular:

// Only graph construction
#include <audio_lab/dependency_graph/graph.hpp>
#include <audio_lab/dependency_graph/graph_builder.hpp>

// Only query interface
#include <audio_lab/dependency_graph/query_engine.hpp>

// Only export functionality
#include <audio_lab/dependency_graph/export_engine.hpp>

// Only metrics
#include <audio_lab/dependency_graph/metrics_engine.hpp>

🔧 CMake Integration

Finding the Package

# In your CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(MyProject)

# Find the dependency graph package
find_package(DependencyGraph 1.0 REQUIRED)

# Link against it
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE
    AudioLab::DependencyGraph
)

Installation Paths

Después de make install:

<prefix>/
├── include/audio_lab/dependency_graph/
│   ├── dependency_graph.hpp
│   ├── graph.hpp
│   ├── graph_builder.hpp
│   ├── query_engine.hpp
│   ├── export_engine.hpp
│   ├── metrics_engine.hpp
│   └── ...
├── lib/cmake/DependencyGraph/
│   ├── DependencyGraphConfig.cmake
│   ├── DependencyGraphTargets.cmake
│   └── DependencyGraphVersion.cmake
└── bin/
    ├── examples/
    │   ├── simple_usage
    │   └── advanced_integration
    └── tools/
        └── graph_cli

Package Configuration

DependencyGraphConfig.cmake:

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/DependencyGraphTargets.cmake")

check_required_components(DependencyGraph)

# Set variables for users
set(DependencyGraph_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@")
set(DependencyGraph_LIBRARIES AudioLab::DependencyGraph)

Version Checking

# Require minimum version
find_package(DependencyGraph 1.2 REQUIRED)

# Check version in code
if(DependencyGraph_VERSION VERSION_LESS "1.2.0")
    message(FATAL_ERROR "Requires DependencyGraph >= 1.2.0")
endif()

📚 Integration Examples

Example 1: Simple Visualization

// simple_usage.cpp
#include <audio_lab/dependency_graph/dependency_graph.hpp>
#include <iostream>

int main() {
    using namespace audio_lab::dependency_graph;

    try {
        // Load catalog
        GraphBuilder builder;
        builder.load_from_catalog("catalog.json");
        Graph graph = builder.build();

        // Print stats
        auto stats = graph.compute_statistics();
        std::cout << "Loaded " << stats.node_count << " modules\n";
        std::cout << "Total dependencies: " << stats.edge_count << "\n";

        // Export visualization
        DotExporter exporter;
        exporter.export_to_file(graph, "output.dot");

        std::cout << "✅ Visualization exported to output.dot\n";
        std::cout << "   Render with: dot -Tpng output.dot -o output.png\n";

        return 0;

    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << "\n";
        return 1;
    }
}

Build:

g++ simple_usage.cpp -o simple_usage \
    -I/usr/local/include \
    -std=c++20

./simple_usage

Example 2: Query and Analysis

// analysis.cpp
#include <audio_lab/dependency_graph/dependency_graph.hpp>
#include <iostream>

int main() {
    using namespace audio_lab::dependency_graph;

    GraphBuilder builder;
    builder.load_from_catalog("catalog.json");
    Graph graph = builder.build();

    // Find expensive modules
    std::cout << "🔍 Finding CPU-expensive modules...\n\n";

    auto expensive = GraphQuery(graph)
        .select_all()
        .where_cpu_greater_than(100)
        .order_by_cpu()
        .limit(10)
        .get_nodes();

    std::cout << "Top 10 CPU-intensive modules:\n";
    for (const auto& node : expensive) {
        std::cout << "  - " << node->label
                  << " (" << node->cpu_cycles << " cycles)\n";
    }

    // Find bottlenecks
    std::cout << "\n🔴 Finding bottlenecks (high fan-in)...\n\n";

    auto bottlenecks = GraphQuery(graph)
        .select_all()
        .where([](const NodePtr& n) {
            return n->in_degree > 5;
        })
        .order_by_degree()
        .get_nodes();

    std::cout << "Bottleneck modules:\n";
    for (const auto& node : bottlenecks) {
        std::cout << "  - " << node->label
                  << " (used by " << node->in_degree << " modules)\n";
    }

    return 0;
}

Example 3: Multi-Format Export

// export_all.cpp
#include <audio_lab/dependency_graph/dependency_graph.hpp>
#include <iostream>

int main(int argc, char* argv[]) {
    using namespace audio_lab::dependency_graph;

    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <catalog.json>\n";
        return 1;
    }

    // Load graph
    GraphBuilder builder;
    builder.load_from_catalog(argv[1]);
    Graph graph = builder.build();

    // Export to all formats
    auto batch = ExportTemplates::full_export();
    batch.set_output_directory("exports/");

    std::cout << "📤 Exporting to all formats...\n";

    auto results = batch.export_all(graph, "dependency_graph");

    // Print results
    std::cout << "\n" << BatchExporter::get_summary(results);

    return 0;
}

Example 4: Integration with Build System

// build_validator.cpp
// Validates that build order is correct based on dependencies

#include <audio_lab/dependency_graph/dependency_graph.hpp>
#include <iostream>

int main(int argc, char* argv[]) {
    using namespace audio_lab::dependency_graph;

    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <catalog.json>\n";
        return 1;
    }

    GraphBuilder builder;
    builder.load_from_catalog(argv[1]);
    Graph graph = builder.build();

    // Check for cycles (invalid for build)
    auto cycles = GraphQuery(graph).get_cycles();

    if (!cycles.empty()) {
        std::cerr << "❌ BUILD ERROR: Dependency cycles detected!\n\n";

        for (size_t i = 0; i < cycles.size(); ++i) {
            std::cerr << "Cycle " << (i + 1) << ": ";
            for (const auto& node_id : cycles[i].path) {
                auto node = graph.get_node(node_id);
                std::cerr << (node ? node->label : node_id) << " → ";
            }
            std::cerr << "(back to start)\n";
        }

        return 1;
    }

    // Get valid build order
    auto build_order = GraphQuery(graph)
        .select_all()
        .topological_sort()
        .get_nodes();

    std::cout << "✅ Valid build order:\n\n";

    for (size_t i = 0; i < build_order.size(); ++i) {
        std::cout << (i + 1) << ". " << build_order[i]->label << "\n";
    }

    // Export to file for build system
    std::ofstream build_file("build_order.txt");
    for (const auto& node : build_order) {
        build_file << node->id << "\n";
    }

    std::cout << "\n📄 Build order written to build_order.txt\n";

    return 0;
}

🔌 Integration Patterns

Pattern 1: Embedded Visualization

Integrar visualización en tu aplicación:

class MyApplication {
private:
    audio_lab::dependency_graph::Graph dependency_graph_;

public:
    void load_modules(const std::string& catalog_path) {
        using namespace audio_lab::dependency_graph;

        GraphBuilder builder;
        builder.load_from_catalog(catalog_path);
        dependency_graph_ = builder.build();

        // Visualize in UI
        update_visualization();
    }

    void update_visualization() {
        using namespace audio_lab::dependency_graph;

        // Export to JSON for web UI
        JsonExporter exporter;
        std::string json = exporter.export_graph(dependency_graph_);

        // Send to frontend
        send_to_ui(json);
    }

    void analyze_dependencies(const std::string& module_id) {
        using namespace audio_lab::dependency_graph;

        // Get impact analysis
        auto impact = GraphQuery(dependency_graph_)
            .start_from(module_id)
            .traverse_upstream()
            .recursive()
            .get_impact_analysis();

        // Show in UI
        show_impact_report(impact);
    }
};

Pattern 2: CI/CD Integration

Usar en pipeline de CI/CD:

// ci_dependency_check.cpp
#include <audio_lab/dependency_graph/dependency_graph.hpp>

int main() {
    using namespace audio_lab::dependency_graph;

    GraphBuilder builder;
    builder.load_from_catalog("catalog.json");
    Graph graph = builder.build();

    bool has_errors = false;

    // Check 1: No cycles
    if (!GraphQuery(graph).get_cycles().empty()) {
        std::cerr << "❌ Dependency cycles detected\n";
        has_errors = true;
    }

    // Check 2: No hierarchy violations
    // (Implementation would check L3->L0, etc.)

    // Check 3: Complexity limits
    auto stats = graph.compute_statistics();
    if (stats.density > 0.1) {
        std::cerr << "⚠️  Warning: Graph density too high\n";
    }

    return has_errors ? 1 : 0;
}

Pattern 3: Documentation Generation

Auto-generar docs en tu proyecto:

// generate_module_docs.cpp
#include <audio_lab/dependency_graph/dependency_graph.hpp>

int main() {
    using namespace audio_lab::dependency_graph;

    GraphBuilder builder;
    builder.load_from_catalog("modules.json");
    Graph graph = builder.build();

    // Generate complete documentation
    DocumentationGenerator doc_gen(graph);
    doc_gen.set_output_directory("docs/modules/");
    doc_gen.enable_markdown(true);
    doc_gen.generate_all();

    std::cout << "✅ Module documentation generated\n";

    return 0;
}

🎛️ Configuration Options

Runtime Configuration

// Configure subsystems at runtime
GraphBuilder builder;

// Set custom JSON parser
builder.set_json_parser(my_custom_parser);

// Configure export options
ExportOptions opts;
opts.include_metadata = true;
opts.pretty_print = true;

DotExporter exporter;
exporter.set_options(opts);

Compile-Time Configuration

# In your CMakeLists.txt

# Enable/disable features
set(DEPENDENCY_GRAPH_ENABLE_LIVE_MONITOR ON)
set(DEPENDENCY_GRAPH_ENABLE_WEBSOCKET OFF)

find_package(DependencyGraph REQUIRED)

📊 API Stability

Versioning

Seguimos Semantic Versioning 2.0.0:

  • Major (X.0.0): Breaking changes en API pública
  • Minor (1.X.0): Nuevas features, backward compatible
  • Patch (1.0.X): Bug fixes, no cambios de API

Deprecation Policy

// Deprecated API (removed in v2.0.0)
[[deprecated("Use GraphQuery::select_all() instead")]]
std::vector<NodePtr> get_all_nodes();

// New API (v1.5.0+)
auto nodes = GraphQuery(graph).select_all().get_nodes();

🔗 External Dependencies

Required

  • C++20 compiler (gcc 10+, clang 12+, MSVC 19.28+)
  • CMake 3.20+

Optional

  • nlohmann/json (bundled if not found)
  • Catch2 (for tests only)

Platform Support

Platform Status Notes
Linux ✅ Fully supported Tested on Ubuntu 20.04+
Windows ✅ Fully supported MSVC 2019+, MinGW
macOS ✅ Fully supported Clang on macOS 11+

📖 Integration Guides

For Application Developers

  1. Install the package: cmake --install build --prefix /usr/local
  2. Find in CMakeLists: find_package(DependencyGraph REQUIRED)
  3. Link: target_link_libraries(app AudioLab::DependencyGraph)
  4. Include: #include <audio_lab/dependency_graph/dependency_graph.hpp>
  5. Use: See examples above

For Library Authors

Si estás creando una biblioteca que usa DependencyGraph:

# YourLibConfig.cmake
find_dependency(DependencyGraph 1.0 REQUIRED)

# Don't expose DependencyGraph in public headers
# Keep it as private implementation detail

For Plugin Developers

Usar para validar plugin dependencies:

class PluginValidator {
public:
    bool validate_plugin_dependencies(const Plugin& plugin) {
        using namespace audio_lab::dependency_graph;

        // Build graph of plugin's modules
        Graph plugin_graph = build_plugin_graph(plugin);

        // Check for cycles
        if (!GraphQuery(plugin_graph).get_cycles().empty()) {
            return false;
        }

        // Validate against host capabilities
        return validate_against_host(plugin_graph);
    }
};

🚀 Quick Start

1. Install

cd audio-lab
mkdir build && cd build
cmake ..
make
sudo make install

2. Create Project

# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(MyProject)

set(CMAKE_CXX_STANDARD 20)

find_package(DependencyGraph REQUIRED)

add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE AudioLab::DependencyGraph)

3. Write Code

// main.cpp
#include <audio_lab/dependency_graph/dependency_graph.hpp>
#include <iostream>

int main() {
    using namespace audio_lab::dependency_graph;

    GraphBuilder builder;
    builder.load_from_catalog("catalog.json");
    auto graph = builder.build();

    std::cout << "Modules: " << graph.get_nodes().size() << "\n";

    return 0;
}

4. Build and Run

mkdir build && cd build
cmake ..
make
./my_app

📚 Additional Resources

  • API Reference: See generated Doxygen docs
  • Examples: examples/ directory
  • Tests: 05_02_test_integration/ for usage patterns
  • Issue Tracker: GitHub Issues

🔧 Troubleshooting

CMake can't find DependencyGraph

# Set CMAKE_PREFIX_PATH
cmake -DCMAKE_PREFIX_PATH=/usr/local ..

# Or specify DependencyGraph_DIR
cmake -DDependencyGraph_DIR=/usr/local/lib/cmake/DependencyGraph ..
# Ensure you're linking the library
target_link_libraries(your_target PRIVATE AudioLab::DependencyGraph)

C++20 errors

# Explicitly set C++20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

Parte de: 05_02_DEPENDENCY_GRAPH - Dependency Graph Visualizer Proporciona: Public API, CMake integration, Examples