Global variables are bad?

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

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” (Spaghetti code - Wikipedia).

SteveT

Steve L.

[email protected]

On 1/9/06, John M. [email protected] 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
:slight_smile:
Guess the functional guys hold the high ground here.

On 1/9/06, Lyndon S. [email protected] wrote:

On 1/9/06, Lyndon S. [email protected] wrote:

On 1/9/06, John M. [email protected] 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 :slight_smile:

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.

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

On 1/9/06, Lyndon S. [email protected] 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.

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.

[email protected]

On 1/10/06, David V. [email protected] wrote:

global variables are bad for some reason. I’ve overcome my main hurdle,
:slight_smile:
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.

On 1/10/06, Steve L. [email protected] 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
:slight_smile:

"Another factor is what the language encourages for implementing these
structures. As Charles
Millerhttp://fishbowl.pastiche.org/2005/12/09/humane_interfacessaid
“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

Lyndon S. wrote:

Static methods on helper classes? Eww… Lawks, you call those global
functions, dearie :stuck_out_tongue_winking_eye: 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 :wink: 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. 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 ™ - 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)

On 1/9/06, Lyndon S. [email protected] wrote:

Playing Devils Advocate for the sake of the discussion, a quote from MF :slight_smile: [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] DuckInterface
[2] Humane Interfaces - The Fishbowl