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
(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?

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.

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.

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.

Phil S. 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.

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

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.

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 B.:
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.

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

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

Robert K. писал 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.

On Mon, May 28, 2012 at 4:56 PM, Peter Z. [email protected]
wrote:

Robert K. 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 Sun, May 27, 2012 at 2:33 PM, Phil S. [email protected]
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?

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 May 27, 2012, at 3:06 PM, Phil S. wrote:

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 B.:
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.