Am I justified to use a global variable if it must be used in all scopes?

Hello,
Ever since I started learning Ruby, I've been strongly discouraged
from using global variables
(http://www.caliban.org/ruby/rubyguide.shtml#style)
(http://www.ruby-forum.com/topic/187685#819233).

In a program I'm making, I have a variable (which stores an instance of
a class) that is declared outside of any functions or classes. However,
I need to be able to call its methods from various class and function
scopes, and nothing but a global variable would let me do that. This
variable is simply what the program is centered around, and must be
accessed and edited by various classes. I'm not sure why a global
variable would be such a bad habit in this case, especially since it is
only one.

Can I justify using it?

···

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

Perhaps a singleton class? It seems to me that you're probably in need of
some more abstraction if you feel you need a global variable.

···

On May 27, 2012 8:34 AM, "Phil Stone" <lists@ruby-forum.com> wrote:

Hello,
Ever since I started learning Ruby, I've been strongly discouraged
from using global variables
(The Unofficial Ruby Usage Guide)
(Use of global variables - Rails - Ruby-Forum).

In a program I'm making, I have a variable (which stores an instance of
a class) that is declared outside of any functions or classes. However,
I need to be able to call its methods from various class and function
scopes, and nothing but a global variable would let me do that. This
variable is simply what the program is centered around, and must be
accessed and edited by various classes. I'm not sure why a global
variable would be such a bad habit in this case, especially since it is
only one.

Can I justify using it?

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

Perhaps a singleton class?

A Singleton class of what kind of object?

It seems to me that you're probably in need
of
some more abstraction if you feel you need a global variable.

But this one variable is what the program is based on. To be more
specific, it is an instance of my Heap class, which is edited by
Variable instances and others. I'm not sure how I could abstract that.

···

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

Phil Stone wrote in post #1062294:

I'm not sure why a global
variable would be such a bad habit in this case, especially since it is
only one.

Can I justify using it?

Your description suggests that you don't plan to reassign the Heap
object. In this case I'd use a constant instead.

···

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

Hello,
Ever since I started learning Ruby, I've been strongly discouraged
from using global variables
(The Unofficial Ruby Usage Guide)
(Use of global variables - Rails - Ruby-Forum).

In a program I'm making, I have a variable (which stores an instance of
a class) that is declared outside of any functions or classes. However,
I need to be able to call its methods from various class and function
scopes, and nothing but a global variable would let me do that. This
variable is simply what the program is centered around, and must be
accessed and edited by various classes. I'm not sure why a global
variable would be such a bad habit in this case, especially since it is
only one.

Can I justify using it?

Avoid using globals as much as possible, variables or constants alike. The are very hard to look for where they are coming from, impossible to mock and painful while unit testing in general as they keep persistent state not being reset for individual test cases.

There are many alternatives to using globals, depending on your particular case. The best would be to design your app in a way that an instance can request what it needs from some other instance, possibly made available at instantiation (or via dependency injection). As others suggested, you can use a singleton for a class that provides state for the whole app, which I personally dislike. Or just class methods.

This is what I sometimes use when I need a quick and dirty way to do the job, to be refactored at the earliest opportunity:

=== main script
class App
  def start
    ...
  end

  def self.config
    @config ||= Config.new
  end
end

App.new.start
=== end of main script
=== player.rb
class Player
  def config
    App::config
  end

  def perform
    return if config.idle_mode?
    ...
  end
end
=== end of player.rb

While behaving exactly as a global config would, it makes it possible to mock config on several levels in your unit tests. Besides, you can clearly see where the data is coming from.

Hope this makes sense to you,
Gennady.

···

On May 27, 2012, at 5:33 AM, Phil Stone wrote:

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

Name the class whatever you like. I think 'Jonan' would be an excellent
name, but you might choose a name that more accurately describes its
purpose.

I just wanted to give you an idea of what the program is supposed to do.

@Gennady Bystritsky:
The particulars of your example don't make total sense... what's the
point of having a class method that accesses an instance variable?
What's the effect? Please explain.

For Config.new, were you thinking of a data structure like this one?:

Unfortunately, the class Config is already defined in my Ruby version:

irb(main):001:0> Config
(irb):1: Use RbConfig instead of obsolete and deprecated Config.

···

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

Hello,
Ever since I started learning Ruby, I've been strongly discouraged
from using global variables

Breaking the 'rules' is fine as long as you understand why the rule exists in the first place.

In a program I'm making, I have a variable (which stores an instance of
a class) that is declared outside of any functions or classes. However,
I need to be able to call its methods from various class and function
scopes, and nothing but a global variable would let me do that.

Being forced to use a global like this is a pretty good indicator that your design is wrong.
A good step in the right direction might be to pass your global variable into any methods that need to use it, rather than accessing it directly. This will make it more obvious what is going on and lead to easier to refactor code.

This
variable is simply what the program is centered around, and must be
accessed and edited by various classes. I'm not sure why a global
variable would be such a bad habit in this case, especially since it is
only one.

Can I justify using it?

If your program is small then a global variable may be fine, you likely won't come across any problems, and trying to wrap it in a class my be more work than it's worth.
As your program grows though the chances that the global var will become a hindrance will increase, but so will the opportunity for you to refactor it out of existence, eg. you may find you need to hold more and more application state that necessitates the creation of an App class, etc.

So, yes, use a global if it gets the job done more quickly but don't let it become a habit.

Henry

···

On 28/05/2012, at 12:33 AM, Phil Stone wrote:

There are circumstances where it is reasonable, see the other replies.
However, there's an alternative: define a class which encapsulates
all the processing which needs to be done in your script and make the
Heap a member of this class. Advantage: you don't have global state
and can instantiate the Processor and have all sorts of methods access
the Heap member. If you change your program to do multiple
calculations in parallel you simply instantiate a Processor for each
Thread and need not fear mixing up state of each individual
processing.

In my experience it is extremely rare that I needed global variables -
so rare I can't actually remember the last time I introduced a global
variable myself. If at all I use pre defined globals like $stderr and
the like.

Kind regards

robert

···

On Sun, May 27, 2012 at 2:33 PM, Phil Stone <lists@ruby-forum.com> wrote:

In a program I'm making, I have a variable (which stores an instance of
a class) that is declared outside of any functions or classes. However,
I need to be able to call its methods from various class and function
scopes, and nothing but a global variable would let me do that. This
variable is simply what the program is centered around, and must be
accessed and edited by various classes. I'm not sure why a global
variable would be such a bad habit in this case, especially since it is
only one.

Can I justify using it?

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

Name the class whatever you like. I think 'Jonan' would be an excellent
name, but you might choose a name that more accurately describes its
purpose.

Perhaps something like Runner?
That's pretty general.

This allows you to have other logic around the current heap if you want it,
and it gives you a convenient place for other information that must be
shared by your entire application.

···

On May 27, 2012 9:15 AM, "Phil Stone" <lists@ruby-forum.com> wrote:

> Perhaps a singleton class?
A Singleton class of what kind of object?

> It seems to me that you're probably in need
> of
> some more abstraction if you feel you need a global variable.
But this one variable is what the program is based on. To be more
specific, it is an instance of my Heap class, which is edited by
Variable instances and others. I'm not sure how I could abstract that.

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

Robert Klemme писал 28.05.2012 16:38:

In my experience it is extremely rare that I needed global variables -
so rare I can't actually remember the last time I introduced a global
variable myself. If at all I use pre defined globals like $stderr and
the like.

I find it quite likely that you are using singletons a lot. I'd say that
in Ruby, constants are pretty much scoped global variables.

Note that I'm not saying this is necessarily bad; I just mean that there's
not much difference between "singletons" and "global variables". Both
represent global state, and the global state itself should be regarded as
possibly harmful, not particular manifestations of it.

···

Kind regards

robert

--
   WBR, Peter Zotov.

Name the class whatever you like. I think 'Jonan' would be an excellent
name, but you might choose a name that more accurately describes its
purpose.

I just wanted to give you an idea of what the program is supposed to do.

@Gennady Bystritsky:
The particulars of your example don't make total sense... what's the
point of having a class method that accesses an instance variable?
What's the effect? Please explain.

[Referring to my code that you unfortunately cut from your reply]

First of all, it is not a "regular" instance variable -- it is a class instance variable. A class itself is an object (an instance of class Class), which may have its own instance variables. They are very distinct from instance variables of a particular instance of that class.

Then:

An instance variable cannot be access directly from outside, only via a method. Unlike a global variable, a method can be refactored to add some more behavior later on if needed, or overridden in a subclass.

The method as presented already demonstrates one possible benefit over just a global variable -- "lazy initialization". A config object will not be created until the very first invocation of the method.

Besides, you can mock this method in your unit tests:

require 'mocha'
...
class PlayerTest < Test::Unit::TestCase
  def test_does_nothing_when_idle
    App.expects(:config).returns mock("config", :idle_mode? => true)
    ...
  end
end

For Config.new, were you thinking of a data structure like this one?:
Deneme Bonusu Veren Bahis Siteleri - En iyi Bonus Veren Siteler Nelerdir?

Unfortunately, the class Config is already defined in my Ruby version:

irb(main):001:0> Config
(irb):1: Use RbConfig instead of obsolete and deprecated Config.

It was just an example, first name that came to mind to demonstrate the concept. Define this class inside class App, and it becomes App::Config. Or call it MyGloriousAppState, whatever (hate that name, btw.) And how the class is defined is irrelevant for this discussion.

···

On May 27, 2012, at 3:06 PM, Phil Stone wrote:

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

Robert Klemme писал 28.05.2012 16:38:

In my experience it is extremely rare that I needed global variables -
so rare I can't actually remember the last time I introduced a global
variable myself. If at all I use pre defined globals like $stderr and
the like.

I find it quite likely that you are using singletons a lot.

I don't - meaning: I don't use singletons a lot. The same statement I
made for global variables is true for singletons and constants as
well. Actually I use global state extremely seldom, if at all. I
just don't need it they way I write software.

I'd say that in Ruby, constants are pretty much scoped global variables.

Correct.

Note that I'm not saying this is necessarily bad; I just mean that there's
not much difference between "singletons" and "global variables". Both
represent global state, and the global state itself should be regarded as
possibly harmful, not particular manifestations of it.

Absolutely agree.

Kind regards

robert

···

On Mon, May 28, 2012 at 4:56 PM, Peter Zotov <whitequark@whitequark.org> wrote:

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