Class: Reek::Smells::ControlCouple

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

Overview

Control Coupling occurs when a method or block checks the value of a parameter in order to decide which execution path to take. The offending parameter is often called a Control Couple.

A simple example would be the quoted parameter in the following method:

def write(quoted)
  if quoted
    write_quoted(@value)
  else
    puts @value
  end
end

Control Coupling is a kind of duplication, because the calling method already knows which path should be taken.

Control Coupling reduces the code’s flexibility by creating a dependency between the caller and callee: any change to the possible values of the controlling parameter must be reflected on both sides of the call.

A Control Couple also reveals a loss of simplicity: the called method probably has more than one responsibility, because it includes at least two different code paths.

Constant Summary

Constants inherited from SmellDetector

SmellDetector::ENABLED_KEY, SmellDetector::EXCLUDE_KEY

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from SmellDetector

class_name, #examine, #exception?, listen, #smell_name

Constructor Details

#initialize(config = ControlCouple.default_config) ⇒ ControlCouple

Returns a new instance of ControlCouple.



46
47
48
# File 'lib/reek/smells/control_couple.rb', line 46

def initialize(config = ControlCouple.default_config)
  super
end

Class Method Details

.contextsObject

:nodoc:



38
39
40
# File 'lib/reek/smells/control_couple.rb', line 38

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

.default_configObject



42
43
44
# File 'lib/reek/smells/control_couple.rb', line 42

def self.default_config
  super.adopt(EXCLUDE_KEY => ['initialize'])
end

Instance Method Details

#examine_context(cond, report) ⇒ Object

Checks whether the given conditional statement relies on a control couple. Any smells found are added to the report.



54
55
56
57
58
# File 'lib/reek/smells/control_couple.rb', line 54

def examine_context(cond, report)
  return unless cond.tests_a_parameter?
  report << SmellWarning.new(self, cond,
              "is controlled by argument #{SexpFormatter.format(cond.if_expr)}")
end