How to avoid global variable?

Every tutorial I read says global variables are bad, but I'm struggling
with the ways to avoid them. In this case (wich actually works), I have
3 files - each having it's own class and purpose. Class Menu is where
program begins. Class Mynumbers should generate a bunch of variables
through calculations. Class Myfiles should be able to read/write those
variables ... very simplified version of my program looks like this:

···

-------------------------------------
#menu.rb

require_relative "myfiles.rb"
require_relative "mynumbers.rb"

class Menu
  def initialize
    $nums = Mynumbers.new
    $nums.calculate
    Myfiles.show
  end
end

start = Menu.new
-------------------------------------
#mynumbers.rb

class Mynumbers
  attr_reader :my_var1, :my_var2

  def calculate
    @my_var1 = rand(2..31)
    @my_var2 = rand(200..310)
  end
end
------------------------------------
#myfiles.rb

class Myfiles
  def self.show
    puts $nums.class
    puts $nums.my_var1
    puts $nums.my_var2.inspect
  end
end
-------------------------------------

TL;DR - is there a way to avoid using global instance $nums ?
(and is there really a reason for that, since my program works)

--
Posted via http://www.ruby-forum.com/.

You want to make variables as local as possible. Then, you want to make things constants whenever possible. When I write straight scripts I tend to always make everything a Constant (begins with uppercase) until I find something that needs otherwise, which turns out to be more rare than most people think.

···

On 11/05/2013 08:10 AM, Stu P. D'naim wrote:

Every tutorial I read says global variables are bad, but I'm struggling
with the ways to avoid them. In this case (wich actually works), I have
3 files - each having it's own class and purpose. Class Menu is where
program begins. Class Mynumbers should generate a bunch of variables
through calculations. Class Myfiles should be able to read/write those
variables ... very simplified version of my program looks like this:

-------------------------------------
#menu.rb

require_relative "myfiles.rb"
require_relative "mynumbers.rb"

class Menu
   def initialize
     $nums = Mynumbers.new
     $nums.calculate
     Myfiles.show
   end
end

start = Menu.new
-------------------------------------
#mynumbers.rb

class Mynumbers
   attr_reader :my_var1, :my_var2

   def calculate
     @my_var1 = rand(2..31)
     @my_var2 = rand(200..310)
   end
end
------------------------------------
#myfiles.rb

class Myfiles
   def self.show
     puts $nums.class
     puts $nums.my_var1
     puts $nums.my_var2.inspect
   end
end
-------------------------------------

TL;DR - is there a way to avoid using global instance $nums ?
(and is there really a reason for that, since my program works)

Excerpts from Stu P. D'naim's message of 2013-11-05 17:10:30 +0100:

Every tutorial I read says global variables are bad, but I'm struggling
with the ways to avoid them. In this case (wich actually works), I have
3 files - each having it's own class and purpose. Class Menu is where
program begins. Class Mynumbers should generate a bunch of variables
through calculations. Class Myfiles should be able to read/write those
variables ... very simplified version of my program looks like this:

-------------------------------------
#menu.rb

require_relative "myfiles.rb"
require_relative "mynumbers.rb"

class Menu
  def initialize
    $nums = Mynumbers.new
    $nums.calculate
    Myfiles.show
  end
end

start = Menu.new
-------------------------------------
#mynumbers.rb

class Mynumbers
  attr_reader :my_var1, :my_var2

  def calculate
    @my_var1 = rand(2..31)
    @my_var2 = rand(200..310)
  end
end
------------------------------------
#myfiles.rb

class Myfiles
  def self.show
    puts $nums.class
    puts $nums.my_var1
    puts $nums.my_var2.inspect
  end
end
-------------------------------------

TL;DR - is there a way to avoid using global instance $nums ?
(and is there really a reason for that, since my program works)

You can replace the global variable $nums with a local variable in Menu
and make MyClass.show take an argument:

class Menu
  def initialize
    nums = Mynumbers.new
    nums.calculate
    Myfiles.show nums
  end
end

class Myfiles
  def self.show ns
    puts ns.class
    puts ns.my_var1
    puts ns.my_var2.inspect
  end
end

If this is only a toy program which won't grow much in size, you can
leave it as it is. However, if you think it'll become larger, in my
opinion, you should make the effort of getting rid of global variables
now, rather than having to do so later when the code has become more
complex.

I hope this helps

Stefano

I hope this helps

Stefano

yes, this is great, it didn't occur to me that you can pass instance
object as an argument ... I think now I will be able to use my variables
that I declare in one class throughout my program (and within all other
classes). Thank you for your time looking at my feeble code !

···

--
Posted via http://www.ruby-forum.com/\.

I'd have a slightly different organization of the code. For example, a
general rule is to not do work in constructors but rather
initialization.

Then, there is really no need to tie Myfiles's functionality to the
class instance. People may want to have several of them - that is
more flexible.

···

On Tue, Nov 5, 2013 at 8:47 PM, Stu P. D'naim <lists@ruby-forum.com> wrote:

yes, this is great, it didn't occur to me that you can pass instance
object as an argument ... I think now I will be able to use my variables
that I declare in one class throughout my program (and within all other
classes). Thank you for your time looking at my feeble code !

-------------------------------------
#menu.rb

require_relative "myfiles.rb"
require_relative "mynumbers.rb"

class Menu
  attr_reader :nums

  def initialize
    @nums = Mynumbers.new
    @nums.calculate
  end
end

# main program

menu = Menu.new
files = Myfiles.new menu
files.show

-------------------------------------
#mynumbers.rb

class Mynumbers
  attr_reader :my_var1, :my_var2

  def calculate
    @my_var1 = rand(2..31)
    @my_var2 = rand(200..310)
  end
end
------------------------------------
#myfiles.rb

class Myfiles
  def initialize menue
    @menue = menue
  end

  def show
    nums = @menue.nums
    puts nums.class
    puts nums.my_var1
    puts nums.my_var2.inspect
  end
end
-------------------------------------

Note, I have no idea what Myfiles really does. It may make sense for a
more realistic example to make Myfiles a member of Menu.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/