Class: RailsFlowMap::MetricsFormatter

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_flow_map/formatters/metrics_formatter.rb

Instance Method Summary collapse

Constructor Details

#initialize(graph) ⇒ MetricsFormatter

Returns a new instance of MetricsFormatter.



3
4
5
# File 'lib/rails_flow_map/formatters/metrics_formatter.rb', line 3

def initialize(graph)
  @graph = graph
end

Instance Method Details

#format(graph = @graph) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/rails_flow_map/formatters/metrics_formatter.rb', line 7

def format(graph = @graph)
  output = []
  output << "# 📊 Rails Application Metrics Report"
  output << "Generated at: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
  output << "\n" + "=" * 60 + "\n"
  
  # 概要統計
  output << "## 📈 Overview Statistics"
  output << "- Total Nodes: #{graph.node_count}"
  output << "- Total Edges: #{graph.edge_count}"
  output << "- Models: #{graph.nodes_by_type(:model).count}"
  output << "- Controllers: #{graph.nodes_by_type(:controller).count}"
  output << "- Actions: #{graph.nodes_by_type(:action).count}"
  output << "- Services: #{graph.nodes_by_type(:service).count}"
  output << "- Routes: #{graph.nodes_by_type(:route).count}"
  
  # 複雑度分析
  output << "\n## 🏆 Complexity Analysis"
  output << "\n### Most Connected Models (by relationships)"
  model_complexity = calculate_node_complexity(graph, :model)
  model_complexity.first(5).each_with_index do |(node, score), index|
    output << "#{index + 1}. #{node.name} (connections: #{score})"
  end
  
  output << "\n### Most Complex Controllers (by actions)"
  controller_actions = {}
  graph.nodes_by_type(:controller).each do |controller|
    action_count = graph.edges.count { |e| e.from == controller.id && e.type == :has_action }
    controller_actions[controller] = action_count
  end
  controller_actions.sort_by { |_, count| -count }.first(5).each_with_index do |(controller, count), index|
    output << "#{index + 1}. #{controller.name} (actions: #{count})"
  end
  
  # 依存関係分析
  output << "\n## 🔗 Dependency Analysis"
  output << "\n### Models with Most Dependencies"
  model_dependencies = calculate_dependencies(graph, :model)
  model_dependencies.first(5).each_with_index do |(node, deps), index|
    output << "#{index + 1}. #{node.name}"
    output << "   - Outgoing: #{deps[:outgoing]} (#{deps[:outgoing_types].join(', ')})"
    output << "   - Incoming: #{deps[:incoming]} (#{deps[:incoming_types].join(', ')})"
  end
  
  # サービス層分析
  output << "\n## 🛠️ Service Layer Analysis"
  services = graph.nodes_by_type(:service)
  if services.any?
    output << "- Total Services: #{services.count}"
    output << "- Services per Controller: #{(services.count.to_f / graph.nodes_by_type(:controller).count).round(2)}"
    
    output << "\n### Most Used Services"
    service_usage = calculate_service_usage(graph)
    service_usage.first(5).each_with_index do |(service, count), index|
      output << "#{index + 1}. #{service.name} (used by #{count} actions)"
    end
  else
    output << "- No service layer detected"
  end
  
  # 潜在的な問題
  output << "\n## ⚠️ Potential Issues"
  
  # 循環依存のチェック
  circular = detect_circular_dependencies(graph)
  if circular.any?
    output << "\n### Circular Dependencies Detected: #{circular.count}"
    circular.each do |cycle|
      output << "- #{cycle.join(' → ')}"
    end
  else
    output << "\n### ✅ No circular dependencies detected"
  end
  
  # God オブジェクトの検出
  output << "\n### Potential God Objects (high connectivity)"
  god_objects = model_complexity.select { |_, score| score > 10 }
  if god_objects.any?
    god_objects.each do |(node, score)|
      output << "- ⚠️ #{node.name} has #{score} connections"
    end
  else
    output << "- ✅ No god objects detected"
  end
  
  # 推奨事項
  output << "\n## 💡 Recommendations"
  
  if model_complexity.first[1] > 15
    output << "- Consider breaking down #{model_complexity.first[0].name} - it has too many relationships"
  end
  
  if services.empty? && graph.nodes_by_type(:controller).count > 5
    output << "- Consider implementing a service layer to separate business logic"
  end
  
  fat_controllers = controller_actions.select { |_, count| count > 7 }
  if fat_controllers.any?
    output << "- These controllers have too many actions: #{fat_controllers.keys.map(&:name).join(', ')}"
    output << "  Consider splitting into multiple controllers or using namespaces"
  end
  
  output.join("\n")
end