Class: Reek::Smells::SimulatedPolymorphism

Inherits:
SmellDetector show all
Defined in:
lib/reek/smells/simulated_polymorphism.rb

Overview

Simulated Polymorphism occurs when

  • code uses a case statement (especially on a type field);

  • or code has several if statements in a row (especially if they’re comparing against the same value);

  • or code uses instance_of?, kind_of?, is_a?, or === to decide what type it’s working with;

  • or multiple conditionals in different places test the same value.

Conditional code is hard to read and understand, because the reader must hold more state in his head. When the same value is tested in multiple places throughout an application, any change to the set of possible values will require many methods and classes to change. Tests for the type of an object may indicate that the abstraction represented by that type is not completely defined (or understood).

In the current implementation, Reek only checks for multiple conditionals testing the same value throughout a single class.

Constant Summary collapse

MAX_IDENTICAL_IFS_KEY =

The name of the config field that sets the maximum number of identical conditionals permitted within any single class.

'max_ifs'
DEFAULT_MAX_IFS =
2

Constants inherited from SmellDetector

Reek::Smells::SmellDetector::DEFAULT_EXCLUDE_SET, Reek::Smells::SmellDetector::EXCLUDE_KEY

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from SmellDetector

class_name, #configure, #configure_with, #copy, create, #enabled?, #examine, #exception?, #found, #has_smell?, listen, #listen_to, #num_smells, #report_on, #smell_name, #smelly?, #supersede_with, #value

Constructor Details

#initialize(config = SimulatedPolymorphism.default_config) ⇒ SimulatedPolymorphism

Returns a new instance of SimulatedPolymorphism.



41
42
43
# File 'lib/reek/smells/simulated_polymorphism.rb', line 41

def initialize(config = SimulatedPolymorphism.default_config)
  super(config)
end

Class Method Details

.contextsObject

:nodoc:



27
28
29
# File 'lib/reek/smells/simulated_polymorphism.rb', line 27

def self.contexts      # :nodoc:
  [:class]
end

.default_configObject



37
38
39
# File 'lib/reek/smells/simulated_polymorphism.rb', line 37

def self.default_config
  super.adopt(MAX_IDENTICAL_IFS_KEY => DEFAULT_MAX_IFS)
end

Instance Method Details

#examine_context(klass) ⇒ Object

Checks the given ClassContext for multiple identical conditional tests. Remembers any smells found.



49
50
51
52
53
54
55
# File 'lib/reek/smells/simulated_polymorphism.rb', line 49

def examine_context(klass)
  counts = Hash.new(0)
  klass.conditionals.each {|cond| counts[cond] += 1}
  counts.each do |key, val|
    found(klass, "tests #{SexpFormatter.format(key)} at least #{val} times") if val > value(MAX_IDENTICAL_IFS_KEY, klass, DEFAULT_MAX_IFS)
  end
end