Global variables considered harmful?

Hello all,

I have a Ruby script here that acts like a regular Unix program,
including
accepting a large number of command-line options/arguments. After
processing
some are simple flags (ie: nil or 1) and some are text/numeric
arguments.
Not all are required, and some must be initialized with a default value.
I
have currently implemented them as globals, as their values are needed
anywhere in my script, from classes to functions to top-level flow
control
code…

Now I know you are not supposed to rely on globals if you can help it,
so I am
trying to rewrite my script to do away with them. The problem is that
there
are so many command-line switches that simply passing them to the
class/function(s) that need them would be unwieldy.

So what do I do? I was thinking of creating and populating a new class
that
would act similar to a C ‘struct’, but it seems to me that this is just
a
different way to do the exact same thing as I have now, except that I
would
have to qualify the variable with a class instance making my script even
more
verbose than it is now…so why shouldn’t we use globals again? Is it
simply
the namespace issue or are there other reasons?

Is one global hash better than 15 global scalars?

I am not going to list my code here because it is 500+ lines but if you
want
to see it let me know and I will post it to the web,

Thanks for consideration,
-d

On 8/8/06, darren kirby [email protected] wrote:

Now I know you are not supposed to rely on globals if you can help it, so I am

  • Dennis Ritchie and Ken Thompson, June 1972

Look at optparse for a better way to do command line arguments. Look
at OpenStruct for a better way to pass them around your program.

On Aug 8, 2006, at 2:37 PM, Francis C. wrote:

Look at optparse for a better way to do command line arguments. Look
at OpenStruct for a better way to pass them around your program.

I imagine a plain Struct is sufficient here, since all of the values
are known before the code even runs.

James Edward G. II

darren kirby wrote:

Now I know you are not supposed to rely on globals if you can help it, so I am

  • Dennis Ritchie and Ken Thompson, June 1972
    Well, this is quite a “can of worms” topic, now isn’t it? For whatever
    its worth, here’s what I do: I have a base class I’ve been working on
    over time from which I derive all of my other scripts. In this base
    class I have all of the logic to configure the script, from command
    line options, to environment vars to config files along with a bunch of
    handy helper methods for things like logging and debugging. The
    results of the configuration go into member variables of this base
    class, or optionally a hash of properties, and thereby form the context
    in which the actual script/application runs. Sure, these are really
    global variables packaged up in the base class but at least they are
    encapsulate and the script doesn’t know where they came from or how
    they got there. This has worked pretty well for me over time for a
    variety of program sizes.

Now then, the direction I’ve been heading in lately has been toward
“inversion of control” (see
Inversion of Control Containers and the Dependency Injection pattern for a very nice
presentation of the topic.) I envision going to a Dependency Injection
pattern some time soon in which the configuration information is
obtained from an inversion control container, as described by Fowler.
But I think I’d only go to this level of “complexity” for true
applications and not for hundren line “scripts”.

Hope this helps.

Ken

quoth the Francis C.:

On 8/8/06, darren kirby [email protected] wrote:

Look at optparse for a better way to do command line arguments. Look
at OpenStruct for a better way to pass them around your program.

Hi,

I am already using getOptLong to parse the command line and it works
fine, are
you saying that optparse is preferable here?

In any event, using a plain or open struct seems like a better way to go
than
using a class.

Thanks guys,
-d

quoth the [email protected]:

Well, this is quite a “can of worms” topic, now isn’t it?

He, well, I certainly didn’t intend for it, I am simply a self-taught
programmer who lacking a formal education tries to muddle through and
pick up
some sage advice from here and there when possible…

encapsulate and the script doesn’t know where they came from or how
But I think I’d only go to this level of “complexity” for true
applications and not for hundren line “scripts”.

Hmm, that link you posted was a little over my head. I understand the
concepts
presented on the “inversion of control” page, but that is about it…

Hope this helps.

As I was basically just fishing for ideas, sure it did, thanks!

Ken

-d

On Aug 8, 2006, at 2:50 PM, [email protected] wrote:

Sure, these are really
global variables packaged up in the base class but at least they are
encapsulate and the script doesn’t know where they came from or how
they got there.

You can also make the class a singleton so all code works with just
one configuration object:

require “singleton”
=> true

class Config
include Singleton
end
=> Config

p Config.instance.object_id
1651794
=> nil

and later, in an unrelated piece of code…

?> p Config.instance.object_id
1651794
=> nil

James Edward G. II

On Wed, 9 Aug 2006, darren kirby wrote:

I have a Ruby script here that acts like a regular Unix program, including
accepting a large number of command-line options/arguments. After processing
some are simple flags (ie: nil or 1) and some are text/numeric arguments.
Not all are required, and some must be initialized with a default value. I
have currently implemented them as globals, as their values are needed
anywhere in my script, from classes to functions to top-level flow control
code…

I tend to parcel such things up into a Context object. Sort of like…

class MyProgContext

def initialize( argv)
parse_args( argv)
sanity_check
end

def print_help_and_exit( plain=“Usage:-”)
puts "
#{plaint}

myprog [options] arg1 arg2

Description

"
exit( 1)
end

end

context = MyProgContext.new( ARGV)

Advantages :-

  • Collects all the stuff neatly into a class.
  • Allows me to enforce invariants (ie. sanity check options /
    arguments for
    mutual compatibility / sanity.
  • Easy to unit test the ARGV parsing logic.

John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [email protected]
New Zealand

Carter’s Clarification of Murphy’s Law.

“Things only ever go right so that they may go more spectacularly wrong
later.”

From this principle, all of life and physics may be deduced.