Class: Reek::SmellDetectors::DataClump
- Inherits:
-
BaseDetector
- Object
- BaseDetector
- Reek::SmellDetectors::DataClump
- Defined in:
- lib/reek/smell_detectors/data_clump.rb
Overview
A Data Clump occurs when the same two or three items frequently appear together in classes and parameter lists, or when a group of instance variable names start or end with similar substrings.
The recurrence of the items often means there is duplicate code spread around to handle them. There may be an abstraction missing from the code, making the system harder to understand.
Currently Reek looks for a group of two or more parameters with the same names that are expected by three or more methods of a class.
See Data-Clump for details.
Constant Summary collapse
- MAX_COPIES_KEY =
The name of the config field that sets the maximum allowed copies of any clump. No group of common parameters will be reported as a DataClump unless there are more than this many methods containing those parameters.
'max_copies'
- DEFAULT_MAX_COPIES =
2
- MIN_CLUMP_SIZE_KEY =
The name of the config field that sets the minimum clump size. No group of common parameters will be reported as a DataClump unless it contains at least this many parameters.
'min_clump_size'
- DEFAULT_MIN_CLUMP_SIZE =
2
Constants inherited from BaseDetector
BaseDetector::DEFAULT_EXCLUDE_SET, BaseDetector::EXCLUDE_KEY
Instance Attribute Summary
Attributes inherited from BaseDetector
Class Method Summary collapse
Instance Method Summary collapse
- #candidate_clumps ⇒ Object private
- #candidate_methods ⇒ Object private
- #clumps ⇒ Object private
- #common_argument_names_for(methods) ⇒ Object private
- #max_copies ⇒ Object private
- #methods_containing_clump(clump) ⇒ Object private
- #min_clump_size ⇒ Object private
-
#sniff ⇒ Array<SmellWarning>
Checks the given class or module for multiple identical parameter sets.
Methods inherited from BaseDetector
#config_for, configuration_keys, descendants, #enabled?, #exception?, #expression, inherited, #initialize, #run, smell_type, #smell_type, #smell_warning, #source_line, to_detector, todo_configuration_for, #value
Constructor Details
This class inherits a constructor from Reek::SmellDetectors::BaseDetector
Class Method Details
.contexts ⇒ Object
:nodoc:
38 39 40 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 38 def self.contexts # :nodoc: [:class, :module] end |
.default_config ⇒ Object
42 43 44 45 46 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 42 def self.default_config super.merge( MAX_COPIES_KEY => DEFAULT_MAX_COPIES, MIN_CLUMP_SIZE_KEY => DEFAULT_MIN_CLUMP_SIZE) end |
.print_clump(clump) ⇒ Object
68 69 70 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 68 def self.print_clump(clump) "[#{clump.map { |parameter| "'#{parameter}'" }.join(', ')}]" end |
Instance Method Details
#candidate_clumps ⇒ Object (private)
86 87 88 89 90 91 92 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 86 def candidate_clumps candidate_methods.combination(max_copies + 1).map do |methods| common_argument_names_for(methods) end.select do |clump| clump.length >= min_clump_size end.uniq end |
#candidate_methods ⇒ Object (private)
82 83 84 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 82 def candidate_methods @candidate_methods ||= context.node_instance_methods end |
#clumps ⇒ Object (private)
103 104 105 106 107 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 103 def clumps candidate_clumps.map do |clump| [clump, methods_containing_clump(clump)] end end |
#common_argument_names_for(methods) ⇒ Object (private)
95 96 97 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 95 def common_argument_names_for(methods) methods.map(&:arg_names).inject(:&).compact.sort end |
#max_copies ⇒ Object (private)
74 75 76 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 74 def max_copies @max_copies ||= value(MAX_COPIES_KEY, context) end |
#methods_containing_clump(clump) ⇒ Object (private)
99 100 101 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 99 def methods_containing_clump(clump) candidate_methods.select { |method| clump & method.arg_names == clump } end |
#min_clump_size ⇒ Object (private)
78 79 80 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 78 def min_clump_size @min_clump_size ||= value(MIN_CLUMP_SIZE_KEY, context) end |
#sniff ⇒ Array<SmellWarning>
Checks the given class or module for multiple identical parameter sets.
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/reek/smell_detectors/data_clump.rb', line 53 def sniff clumps.map do |clump, methods| methods_length = methods.length smell_warning( lines: methods.map(&:line), message: "takes parameters #{DataClump.print_clump(clump)} " \ "to #{methods_length} methods", parameters: { parameters: clump.map(&:to_s), count: methods_length }) end end |