Class: Reek::Smells::FeatureEnvy

Inherits:
SmellDetector show all
Includes:
ExcludeInitialize
Defined in:
lib/reek/smells/feature_envy.rb

Overview

Feature Envy occurs when a code fragment references another object more often than it references itself, or when several clients do the same series of manipulations on a particular type of object.

A simple example would be the following method, which “belongs” on the Item class and not on the Cart class:

class Cart
  def price
    @item.price + @item.tax
  end
end

Feature Envy reduces the code's ability to communicate intent: code that “belongs” on one class but which is located in another can be hard to find, and may upset the “System of Names” in the host class.

Feature Envy also affects the design's flexibility: A code fragment that is in the wrong class creates couplings that may not be natural within the application's domain, and creates a loss of cohesion in the unwilling host class.

Currently FeatureEnvy reports any method that refers to self less often than it refers to (ie. send messages to) some other object.

Constant Summary

Constants inherited from SmellDetector

SmellDetector::DEFAULT_EXCLUDE_SET, SmellDetector::EXCLUDE_KEY

Instance Attribute Summary

Attributes inherited from SmellDetector

#smell_category, #smell_type, #smells_found, #source

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ExcludeInitialize

default_config

Methods inherited from SmellDetector

#config_for, #configure_with, contexts, default_config, default_smell_category, #enabled?, #enabled_for?, #examine, #exception?, #initialize, #register, #report_on, smell_type, #value

Constructor Details

This class inherits a constructor from Reek::Smells::SmellDetector

Class Method Details

.smell_categoryObject


36
37
38
# File 'lib/reek/smells/feature_envy.rb', line 36

def self.smell_category
  'LowCohesion'
end

Instance Method Details

#examine_context(method_ctx) ⇒ Array<SmellWarning>

Checks whether the given context includes any code fragment that might “belong” on another class.

Returns:


46
47
48
49
50
51
52
53
54
55
# File 'lib/reek/smells/feature_envy.rb', line 46

def examine_context(method_ctx)
  method_ctx.envious_receivers.map do |ref, occurs|
    target = ref.format_ruby
    SmellWarning.new self,
                     context: method_ctx.full_name,
                     lines: [method_ctx.exp.line],
                     message: "refers to #{target} more than self",
                     parameters: { name: target, count: occurs }
  end
end