Class: Solidarity::SolidEvaluator
- Inherits:
-
Object
- Object
- Solidarity::SolidEvaluator
- Defined in:
- lib/solidarity/solid_evaluator.rb
Instance Method Summary collapse
- #evaluate_all ⇒ Object
- #evaluate_dip ⇒ Object
- #evaluate_isp ⇒ Object
- #evaluate_lsp ⇒ Object
- #evaluate_ocp ⇒ Object
- #evaluate_srp ⇒ Object
-
#initialize(graph) ⇒ SolidEvaluator
constructor
A new instance of SolidEvaluator.
Constructor Details
#initialize(graph) ⇒ SolidEvaluator
Returns a new instance of SolidEvaluator.
3 4 5 |
# File 'lib/solidarity/solid_evaluator.rb', line 3 def initialize(graph) @graph = graph end |
Instance Method Details
#evaluate_all ⇒ Object
64 65 66 67 68 69 70 71 72 |
# File 'lib/solidarity/solid_evaluator.rb', line 64 def evaluate_all { srp: evaluate_srp, ocp: evaluate_ocp, lsp: evaluate_lsp, isp: evaluate_isp, dip: evaluate_dip } end |
#evaluate_dip ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/solidarity/solid_evaluator.rb', line 43 def evaluate_dip # Dependency Inversion Principle (DIP) # Heuristic: High-level modules should depend on abstractions, not concretions. # We can look for dependencies from concrete classes to other concrete classes as a potential violation. # This requires distinguishing between abstract/concrete classes, which railroady doesn't explicitly provide. dip_score = 100 # For now, a very simplistic view: count edges between concrete classes. # This needs significant refinement to be meaningful. # concrete_to_concrete_dependencies = 0 # Placeholder # @graph.edges.each do |edge| # source_node = @graph.find_node(edge.source) # target_node = @graph.find_node(edge.target) # if source_node&.type == :class && target_node&.type == :class # Assuming :class is concrete # concrete_to_concrete_dependencies += 1 # end # end # dip_score = (100 - concrete_to_concrete_dependencies * 5).clamp(0, 100) { score: dip_score, details: "DIP assessment requires distinguishing abstract from concrete classes." } end |
#evaluate_isp ⇒ Object
36 37 38 39 40 41 |
# File 'lib/solidarity/solid_evaluator.rb', line 36 def evaluate_isp # Interface Segregation Principle (ISP) # Heuristic: Could look for modules included by many classes but with few used methods by each class. # Requires method-level analysis, which is not available from railroady's DOT output. { score: 70, details: "ISP is difficult to assess without method-level dependency analysis." } end |
#evaluate_lsp ⇒ Object
29 30 31 32 33 34 |
# File 'lib/solidarity/solid_evaluator.rb', line 29 def evaluate_lsp # Liskov Substitution Principle (LSP) # Very hard to evaluate statically from a dependency graph. Requires behavioral analysis. # Placeholder: Assume a perfectly flat hierarchy (no deep inheritance) is better, but this is a very weak heuristic. { score: 70, details: "LSP is difficult to assess statically from a dependency graph." } end |
#evaluate_ocp ⇒ Object
19 20 21 22 23 24 25 26 27 |
# File 'lib/solidarity/solid_evaluator.rb', line 19 def evaluate_ocp # Open/Closed Principle (OCP) # Heuristic: Presence of inheritance/module inclusions. Hard to measure purely from dependency graph. # A higher number of classes participating in inheritance/module inclusion might suggest better OCP. ocp_score = 0 inheriting_nodes = @graph.edges.count { |edge| edge.type == :inheritance || edge.type == :includes } ocp_score = (inheriting_nodes > @graph.nodes.count / 4) ? 100 : (inheriting_nodes * 100.0 / (@graph.nodes.count / 4)).clamp(0, 100) { score: ocp_score, details: "Number of inheritance/inclusion relationships: #{inheriting_nodes}" } end |
#evaluate_srp ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/solidarity/solid_evaluator.rb', line 7 def evaluate_srp # Single Responsibility Principle (SRP) # Heuristic: High outgoing edges might indicate multiple responsibilities. # For a more accurate measure, we'd need to analyze method calls/dependencies within each class. srp_scores = {} @graph.nodes.each do |node| outgoing_count = @graph.outgoing_edges(node.name).count srp_scores[node.name] = outgoing_count < 5 ? 100 : (100 - (outgoing_count - 5) * 10).clamp(0, 100) end { score: srp_scores.values.sum / srp_scores.size.to_f, details: srp_scores } end |