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¶
- Clean Public API - Headers consolidados sin dependencias internas
- CMake Integration - Find modules y configuración de paquete
- Easy Integration - Ejemplos de uso desde otros proyectos
- Version Management - Compatibilidad y versionado semántico
- 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:
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¶
- Install the package:
cmake --install build --prefix /usr/local - Find in CMakeLists:
find_package(DependencyGraph REQUIRED) - Link:
target_link_libraries(app AudioLab::DependencyGraph) - Include:
#include <audio_lab/dependency_graph/dependency_graph.hpp> - 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¶
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¶
📚 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 ..
Missing symbols at link time¶
# Ensure you're linking the library
target_link_libraries(your_target PRIVATE AudioLab::DependencyGraph)
C++20 errors¶
Parte de: 05_02_DEPENDENCY_GRAPH - Dependency Graph Visualizer Proporciona: Public API, CMake integration, Examples