Class: WhyClasses::Rules::SingleAttributeReader

Inherits:
WhyClasses::Rule show all
Defined in:
lib/why_classes/rules/single_attribute_reader.rb

Overview

Decoupled polymorphism: an instance method that only reads a single field could be a freestanding function that works on anything responding to that field. Off by default -- it is a stylistic nudge and can be noisy.

Constant Summary

Constants inherited from WhyClasses::Rule

WhyClasses::Rule::H

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from WhyClasses::Rule

autocorrectable?, #call, inherited, #initialize, rule_name

Constructor Details

This class inherits a constructor from WhyClasses::Rule

Class Method Details

.descriptionObject



11
12
13
# File 'lib/why_classes/rules/single_attribute_reader.rb', line 11

def self.description
  "Instance method that only reads one field -> consider a freestanding polymorphic function."
end

Instance Method Details

#on_class(node) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/why_classes/rules/single_attribute_reader.rb', line 15

def on_class(node)
  s = shape(node)
  return if s.name.nil?
  return if s.uses_metaprogramming?

  s.behavior_methods.each do |method|
    read = H.ivars_read(method)
    written = H.ivars_assigned(method)
    next unless written.empty?
    next unless read.size == 1

    field = read.first.to_s.delete_prefix("@")
    add_offense(
      method,
      message: "#{s.name}##{method.children[0]} only reads @#{field}; it isn't tied to #{s.name}.",
      suggestion: "A freestanding function is more flexible and works on any object " \
                  "exposing `#{field}`:\n" \
                  "    def #{method.children[0]}(#{field})\n      # use #{field} directly\n    end"
    )
  end
end