boundary_core/
metrics_report.rs1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::types::ArchLayer;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct ClassificationCoverage {
10 pub total_components: usize,
11 pub classified: usize,
12 pub cross_cutting: usize,
13 pub unclassified: usize,
14 pub coverage_percentage: f64,
15 pub unclassified_paths: Vec<String>,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct MetricsReport {
21 pub components_by_kind: HashMap<String, usize>,
22 pub components_by_layer: HashMap<String, usize>,
23 pub violations_by_kind: HashMap<String, usize>,
24 pub dependency_depth: DependencyDepthMetrics,
25 pub layer_coupling: LayerCouplingMatrix,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub classification_coverage: Option<ClassificationCoverage>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct DependencyDepthMetrics {
33 pub max_depth: usize,
34 pub avg_depth: f64,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct LayerCouplingMatrix {
40 pub matrix: HashMap<String, HashMap<String, usize>>,
41}
42
43impl LayerCouplingMatrix {
44 pub fn new() -> Self {
45 let layers = [
46 ArchLayer::Domain,
47 ArchLayer::Application,
48 ArchLayer::Infrastructure,
49 ArchLayer::Presentation,
50 ];
51 let mut matrix = HashMap::new();
52 for from in &layers {
53 let mut row = HashMap::new();
54 for to in &layers {
55 row.insert(to.to_string(), 0);
56 }
57 matrix.insert(from.to_string(), row);
58 }
59 Self { matrix }
60 }
61
62 pub fn increment(&mut self, from: &ArchLayer, to: &ArchLayer) {
63 if let Some(row) = self.matrix.get_mut(&from.to_string()) {
64 if let Some(count) = row.get_mut(&to.to_string()) {
65 *count += 1;
66 }
67 }
68 }
69}
70
71impl Default for LayerCouplingMatrix {
72 fn default() -> Self {
73 Self::new()
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_coupling_matrix_increment() {
83 let mut matrix = LayerCouplingMatrix::new();
84 matrix.increment(&ArchLayer::Domain, &ArchLayer::Infrastructure);
85 matrix.increment(&ArchLayer::Domain, &ArchLayer::Infrastructure);
86 assert_eq!(
87 matrix.matrix["domain"]["infrastructure"], 2,
88 "should count two edges"
89 );
90 }
91}