Forum: Ruby global variables are bad??

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
John M. (Guest)
on 2006-01-09 04:34
(Received via mailing list)
Chaps,

I'm not sure were I have read this but I recall a page or two saying
that global variables are bad for some reason. I've overcome my main
hurdle, of understanding some of the basics of OO.

There's loads of good code  in the following directory:-
/usr/share/doc/ruby-tcltk-1.8.4/tk/sample/demos-en/
which I have used to get me up to speed on widgets and such.


I've seen loads of global variables in
 /usr/share/doc/ruby-tcltk-1.8.4/tk/sample/demos-en/...
care to guide a novice on why global variables are used here?
#============================ start of extract
============================

#!/usr/bin/env ruby

# widget --
# This script demonstrates the various widgets provided by Tk,
# along with many of the features of the Tk toolkit.  This file
# only contains code to generate the main window for the
# application, which invokes individual demonstrations.  The
# code for the actual demonstrations is contained in separate
# ".rb" files is this directory, which are sourced by this script
# as needed.

require 'tk'
# require 'tkafter'

### $DEBUG=1 ##########

#----------------------------------------------------------------
# The code below create the main window, consisting of a menu bar
# and a text widget that explains how to use the program, plus lists
# all of the demos as hypertext items.
#----------------------------------------------------------------

# widget demo directory
$demo_dir = File.dirname($0)

# root
$root = TkRoot.new{title "Ruby/Tk Widget Demonstration"}

# tk
$tk_version = Tk::TK_VERSION
$tk_major_ver, $tk_minor_ver = $tk_version.split('.').map{|n| n.to_i}
$tk_patchlevel = Tk::TK_PATCHLEVEL

# tcl_platform
$tk_platform = TkVarAccess.new('tcl_platform')

#
case($tk_version)
when /^4.*/
  $font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*',
nil)
else
  $font = TkFont.new('Helvetica -12')
end

# images
$image = {}
#============================ end of extract
============================
Steve L. (Guest)
on 2006-01-09 05:53
(Received via mailing list)
On Sunday 08 January 2006 09:33 pm, John M. wrote:
>
> I've seen loads of global variables in
>  /usr/share/doc/ruby-tcltk-1.8.4/tk/sample/demos-en/...
> care to guide a novice on why global variables are used here?

Hi John,

The global vars in the code you quoted were used not as variables, but
as
constants. One wouldn't want to pass all those vars in and out of every
subroutine. As used in the code you quoted, I see nothing wrong with
them,
because in spirit, if not in the letter of the law, they were used as
constants, never again to be modified.

When I have tons of config info like that I usually wrap it in a single
object, which might be global or local and passed, but it's all in one
place.
I find that easier to deal with for config info, even if it's intended
to be
constant.

Global variables used as variables can be a debugging nightmare because
every
single line of code has write access to them, meaning that if a variable
"goes bad", it's very hard to find where it "went bad". You basically
need to
trace through the whole program. Global variables also make a program
much
less modular. In my opinion they're the data equivalent of "spaghetti
programming" (http://en.wikipedia.org/wiki/Spaghetti_code).

SteveT

Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid
Lyndon S. (Guest)
on 2006-01-09 06:02
(Received via mailing list)
On 1/9/06, John M. <removed_email_address@domain.invalid> wrote:
>
> Chaps,
>
> I'm not sure were I have read this but I recall a page or two saying that
> global variables are bad for some reason. I've overcome my main hurdle, of
> understanding some of the basics of OO.


Interestingly it's allmost universally accepted that Global Variables
are
bad ( in the same camp along with GOTO ), yet instance variables are
just a
more restrictive variation on the same theme, yet they are best practice
:-)
Guess the functional guys hold the high ground here.
Eivind E. (Guest)
on 2006-01-09 18:09
(Received via mailing list)
On 1/9/06, Lyndon S. <removed_email_address@domain.invalid> wrote:
Eivind E. (Guest)
on 2006-01-09 23:15
(Received via mailing list)
On 1/9/06, Lyndon S. <removed_email_address@domain.invalid> wrote:
> On 1/9/06, John M. <removed_email_address@domain.invalid> wrote:
> > I'm not sure were I have read this but I recall a page or two saying that
> > global variables are bad for some reason. I've overcome my main hurdle, of
> > understanding some of the basics of OO.
>
> Interestingly it's allmost universally accepted that Global Variables are
> bad ( in the same camp along with GOTO ), yet instance variables are just a
> more restrictive variation on the same theme, yet they are best practice :-)

What's important here is how easy the code is to work with.  Global
variables will usually lead to it being hard to see how different
parts of the program communicate, and make the program behaviour vary
due to a large amount of state stored in a plethora of different
variables.  They also often make it hard to change the program, for
instance to have two of something there used to be only one of.  So
the critique isn't against "global variables" per se - it's against
global variables used in a way that makes it hard to understand and
change a program.  That's the same critique as we have against goto.

Global variables do not always lead to this, and instance variables
can lead to the same problems. And sometimes global variables is the
right solution, leading to a clearer program that's easier to modify.

Just as goto sometimes makes it possible to create programs that's
easier to read.  Especially direct implementations of state machines
tend to be easier to read when written using goto than when written
with a separate variable keeping track of the state.  I've missed goto
in Ruby a couple of times for this (and before somebody jump in: I
know I can sort of implement it using callcc.)

Eivind.
David V. (Guest)
on 2006-01-10 02:35
(Received via mailing list)
Lyndon S. wrote:

>
>
>Interestingly it's allmost universally accepted that Global Variables are
>bad ( in the same camp along with GOTO ), yet instance variables are just a
>more restrictive variation on the same theme, yet they are best practice :-)
>Guess the functional guys hold the high ground here.
>
>
>
The main advantage of instance variables to global variables is that
they allow you to scope the variables down to -very- narrow contexts of
validity, and they can be hidden outside said scope. If that's what you
mean by "more restrictive variation", then scoping is the restriction
that matters. And giving context to relate global variables via naming
conventions sounds pretty painful.

David V.
Lyndon S. (Guest)
on 2006-01-10 05:18
(Received via mailing list)
On 1/10/06, David V. <removed_email_address@domain.invalid> wrote:
> >>global variables are bad for some reason. I've overcome my main hurdle,
> :-)
> >Guess the functional guys hold the high ground here.
> >
> >
> >
> The main advantage of instance variables to global variables is that
> they allow you to scope the variables down to -very- narrow contexts of
> validity, and they can be hidden outside said scope. If that's what you
> mean by "more restrictive variation", then scoping is the restriction
> that matters. And giving context to relate global variables via naming
> conventions sounds pretty painful.


I guess what I was thinking was, conceivably you could have a class with
say
100s of methods, all with full access to any ( private/protected/public
)
instance variables. How is that different to 100s of functions accessing
global variables?




David V.
Jacob F. (Guest)
on 2006-01-10 06:15
(Received via mailing list)
On 1/9/06, Lyndon S. <removed_email_address@domain.invalid> wrote:
> (private/protected/public) instance variables. How is that different to
> 100s of functions accessing global variables?

It's not. Both are bad design. However, in the case of the class +
instance variables, the problem is that you shouldn't have hundreds of
(significant[1]) methods in one class, that's a major code stink --
smell isn't a strong enough word.

Jacob F.

[1] At peril of reopening the "Array has too many methods" can of
worms; yes, I do like convenience methods; no, I don't think Array has
too many methods, although there are a *few* questionable methods in
Array; yada, yada, yada. The important thing is that convenience
methods *should* be built upon the other methods of the class, and
thus not access the instance variables. They are only there, as the
name implies, for convenience.
Steve L. (Guest)
on 2006-01-10 07:15
(Received via mailing list)
On Monday 09 January 2006 10:15 pm, Lyndon S. wrote:

> I guess what I was thinking was, conceivably you could have a class with
> say 100s of methods, all with full access to any ( private/protected/public
> ) instance variables. How is that different to 100s of functions accessing
> global variables?

Why would you do that? With hundreds of methods, wouldn't these hundreds
of
methods tend to categorize in ways that you could split the big class
into
smaller ones?

SteveT

Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid
Lyndon S. (Guest)
on 2006-01-10 07:40
(Received via mailing list)
On 1/10/06, Steve L. <removed_email_address@domain.invalid> wrote:
> Why would you do that? With hundreds of methods, wouldn't these hundreds
> of
> methods tend to categorize in ways that you could split the big class into
> smaller ones?


Playing Devils Advocate for the sake of the discussion, a quote from MF
:-)
http://www.martinfowler.com/bliki/DuckInterface.html

"Another factor is what the language encourages for implementing these
structures. As Charles
Miller<http://fishbowl.pastiche.org/2005/12/09/humane_int...
"Java's design
*affords* small interfaces, and utility functions provided as static
methods
on helper classes. Ruby's design affords larger classes with mixed-in
utility methods."



SteveT
David V. (Guest)
on 2006-01-10 12:36
(Received via mailing list)
Jacob F. wrote:

>>>that matters. And giving context to relate global variables via naming
>It's not. Both are bad design. However, in the case of the class +
>instance variables, the problem is that you shouldn't have hundreds of
>(significant[1]) methods in one class, that's a major code stink --
>smell isn't a strong enough word.
>
>Jacob F.
>
>
I'm with Jacob on that one, if you abuse OO, (or rather fail to make
proper use of it), you can very well end up with code as evil as script
kiddy PHP hacks. Bad code is bad code is bad code, and no language or
paradigm will ever prevent people from being horribly bad at it. And
vice versa, you can make surprisingly clean procedural code if you
enforce granularity and don't rely on global state - GLib comes to mind.

>[1] At peril of reopening the "Array has too many methods" can of
>worms; yes, I do like convenience methods; no, I don't think Array has
>too many methods, although there are a *few* questionable methods in
>Array; yada, yada, yada. The important thing is that convenience
>methods *should* be built upon the other methods of the class, and
>thus not access the instance variables. They are only there, as the
>name implies, for convenience.
>
>
And at peril of joining sides in a holy war I'm not yet well aware of,
I'm taking the stance that people need to distinguish between designing
application (internal) code, and designing library (exported) code. The
former I prefer maintainable and consistent, the outer, which other
people are most likely to make use of, I prefer usable, well supplied
with friendly interfaces that provide Sensible Defaults instead of
having users of my library understand my Great Plan (tm) - which is
something only people that modify a library should care about. The one
argument that speaks against many methods in a class is reduced
maintainability, but I'll buy that one if I see Array getting
convenience methods that aren't implementable with a one-liner.

David V.
.NET bashing for fun and profit. (Because SortedLists are IDictionaries
now)
David V. (Guest)
on 2006-01-10 12:45
(Received via mailing list)
Lyndon S. wrote:

>
>
Static methods on helper classes? Eww... Lawks, you call those global
functions, dearie ;P Java is consistent it not being "magic" at any
time, and keeping to a very minimal set of well known basic language
principles with the good and the bad that brings - the good being it's
easy to grok, the bad the severe lack of flexibility there is for
consistency's sake.

Then one reason people use the kludgy static methods is because it's
usually less typing than properly adding instance methods to your code -
laziness is a big motivator of the efforts of man ;) The other one I can
think of is being unable to extend existing classes within Java, but
should AspectJ and the like ever get to / already have the dark voodoo
of weaving introduction aspects directly into bytecode at startup time,
you can arguably do that using some rather trivial AOP if you swing that
way.

"The language made me do it" is NOT an excuse for bad design.

David V.
.NET bashing for fun and profit (Because SortedLists are IDictionaries
now)
Jacob F. (Guest)
on 2006-01-10 18:38
(Received via mailing list)
On 1/9/06, Lyndon S. <removed_email_address@domain.invalid> wrote:
>
> Playing Devils Advocate for the sake of the discussion, a quote from MF :-) [1]
>
> "Another factor is what the language encourages for implementing these
> structures. As Charles Miller[2] said "Java's design *affords* small interfaces,
> and utility functions provided as static methods on helper classes. Ruby's
> design affords larger classes with mixed-in utility methods."

Let me reconcile what Martin F. is saying there with Steve's
comment. "Ruby's design affords larger classes with /mixed-in utility
methods/" (emphasis added). The size of Array comes mostly from
Enumerable being mixed in. Take away the Enumerable mixin and you have
many fewer methods. Array may override a few of Enumerable's methods
in C for speed, but Array is a special case as a core language
construct, and it still doesn't override the majority. As such,
Array's implementation follows exactly what Steve recommended of
refactoring the bits out into different maintainable chunks. And all
of the methods mixed in by Enumerable are implementation agnostic --
all they require is that you provide an #each method which they build
upon, usually in a one liner. They don't care about or access your
instance variables, which is what this (sub)thread was about in the
first place.

Jacob F.

[1] http://www.martinfowler.com/bliki/DuckInterface.html
[2] http://fishbowl.pastiche.org/2005/12/09/humane_interfaces
This topic is locked and can not be replied to.