global variables are bad??

J

John Maclean

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 ============================
 
S

Steve Litt

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?

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 Litt
http://www.troubleshooters.com
(e-mail address removed)
 
L

Lyndon Samson

------=_Part_4739_1755297.1136779296638
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

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, o= f
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.

------=_Part_4739_1755297.1136779296638--
 
E

Eivind Eklund

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.
 
E

Eivind Eklund

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.
 
D

David Vallner

Lyndon said:
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 Vallner
 
L

Lyndon Samson

------=_Part_15097_9814468.1136862929803
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

t
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 sa=
y
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 Vallner
 
J

Jacob Fugal

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?

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 Fugal

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

Steve Litt

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 Litt
http://www.troubleshooters.com
(e-mail address removed)
 
L

Lyndon Samson

------=_Part_16230_25123566.1136871423167
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

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 int= o
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_interfaces>said
"Java's design
*affords* small interfaces, and utility functions provided as static method=
s
on helper classes. Ruby's design affords larger classes with mixed-in
utility methods."



SteveT
 
D

David Vallner

Jacob said:
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?

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 Fugal
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 Vallner
NET bashing for fun and profit. (Because SortedLists are IDictionaries now)
 
D

David Vallner

Lyndon said:
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_interfaces>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."
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 Vallner
NET bashing for fun and profit (Because SortedLists are IDictionaries now)
 
J

Jacob Fugal

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

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 inte= rfaces,
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 Fowler 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 Fugal

[1] http://www.martinfowler.com/bliki/DuckInterface.html
[2] http://fishbowl.pastiche.org/2005/12/09/humane_interfaces
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top