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::DEFAULT_EXCLUDE_SET, 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 = 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) ⇒ Object

Checks whether the given conditional statement relies on a control couple. Remembers any smells found.



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

def examine_context(cond)
  return unless cond.tests_a_parameter?
  # SMELL: Duplication
  # This smell is reported once for each conditional that tests the
  # same parameter. Which means that the same smell can recur within
  # a single sniffer. Which in turn means that the sniffer can't count
  # its smells without knowing which are duplicates.
  found(cond, "is controlled by argument #{SexpFormatter.format(cond.if_expr)}")
end