Forum: Ruby how to avoid global variable ?

E8f4cff5d676e9ef840fe7a030efc845?d=identicon&s=25 Stu P. D'naim (oldboy)
on 2013-11-05 17:10
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)
8e44b211865cd5915f2f883fd960b56d?d=identicon&s=25 Xeno Campanoli (Guest)
on 2013-11-05 17:26
(Received via mailing list)
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.
C40020a47c6b625af6422b5b1302abaf?d=identicon&s=25 Stefano Crocco (crocco)
on 2013-11-05 17:35
(Received via mailing list)
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
E8f4cff5d676e9ef840fe7a030efc845?d=identicon&s=25 Stu P. D'naim (oldboy)
on 2013-11-05 20:47
> 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 !
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2013-11-05 23:31
(Received via mailing list)
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 !

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
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.