Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid class and global variables

Rubocop confirms to The Ruby Style Guide. It discourages use of anything besides instance variables. I find it confusing to not use at the least class variables. This snippet from the Style Guide frowns on usage of global variables and instead recommends module instance variables:

# bad
$foo_bar = 1

# good
module Foo
  class << self
    attr_accessor :bar
  end
end

Foo.bar = 1

It makes sense to be wary of using global variables, but using neither global nor class variables blows my mind.

Among module instance variables and class instance variables, which is more efficient usage of memory?

For example:

Option A (Class Instance Variable):

# things that exist only with life
module Life
  # an instance of life with unique actions/attributes
  class Person
    attr_accessor :memories

    def initialize
      @memories = []
    end

    def memorize(something)
      @memories << something
    end
  end
end

bob = Life::Person.new
bob.memorize 'birthday'
bob.memorize 'wedding'
bob.memorize 'anniversary'

bob.memories
# => ["birthday", "wedding", "anniversary"]

Option B (Module Instance Variable):

# things that exist only with life
module Life
  # something all living things possess
  module Memory
    class << self
      attr_accessor :memories
    end
  end

  # an instance of life with unique actions/attributes
  class Person
    include Memory

    def initialize
      Memory.memories = []
    end

    def memorize(something)
      Memory.memories << something
    end

    def memories
      Memory.memories
    end
  end
end

bob = Life::Person.new
bob.memorize 'birthday'
bob.memorize 'wedding'
bob.memorize 'anniversary'

bob.memories
# => ["birthday", "wedding", "anniversary"]
like image 451
binarymason Avatar asked Oct 20 '22 01:10

binarymason


1 Answers

You misunderstand the term "class instance variable". It means "instance variable on a Class object", not "instance variable on an instance of some class".

  class Person
    attr_accessor :memories # instance variable, not shared

    class << self
      attr_accessor :memories # class instance variable, shared between
                              # all instances of this class
    end
  end

Obviously, sometimes you do need to use class instance variables. Refrain from using class variables (@@memories) as they are shared between all classes in the hierarchy (the class and its children), which may lead to surprising behaviour.

like image 188
Sergio Tulentsev Avatar answered Oct 22 '22 07:10

Sergio Tulentsev