DEV Community

Discussion on: It's Ruby, There Must Be a Better Way

Collapse
 
tleish profile image
tleish • Edited

Be careful... since self.names is a class method, then this implementation of @names is also a class variable.

So both of these are using class level variables and writing to the global namespace:

class Robot
    def self.names
      @@names = POSSIBLE_NAMES.to_a.shuffle.each
    end
end
Robot.names
Robot.class_variable_get(:@@names)
class Robot
    def self.names
      @names ||= POSSIBLE_NAMES.to_a.shuffle.each
    end
end
Robot.names
Robot.instance_variable_get(:@names)

In this last case, the Robot class is a singleton instance itself.

Class variables are not 'evil' as long as you know what you are doing. Best rule of thumb would be to consider a class variable generally as immutable. In this example, if we had 2 separate processes sharing the same service of make robot names... one could reset the names while the other is running. This would cause a bad side effect. However, if you simple used the class variable to store the initial full set of names and then randomized it with each instance would be safer. Class variable is being used as a constant, immutable value... while random is per instance.

Also, since the built array already exists inside the enumerable, reusing the array is slightly faster than rebuilding from a range each time:

  def self.forget
    @@names = @@names.to_a.shuffle.each
  end