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)

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.

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

require_relative “myfiles.rb”
start = Menu.new
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 !

On Tue, Nov 5, 2013 at 8:47 PM, Stu P. D’naim [email protected]
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 !

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.


#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