Best way to deal with command line options

Hi,

I'm verry new to ruby, just use it for some days now and I have question about the best implementation of how to deal with command line options.

Suppose I have a program, with a class say A and a main.
My program also has a verbose option (program --verbose).
What's the best way to implement the verbose option in a OO-way?

a) give the boolean verbose to the class and let the class control it. (method(verbose) --> puts "something" if verbose)
b) run the program and let the main handle with the verbose option.
c) something else

A second question about this is suppose my program runs a loop for a number of times and the user may specify the number of loops to make, and if the program must run to the end in once or ask for user action every x steps)
like: program --loops 50 --steps 5 --> this would ask for user input every 5yt steps and loops 50 times.

What's the best way to do this?

a) again let the class handle it (a method run(number_of_loops, steps))
b) or let the main handle it (in the class just a method step() and in the main the method run(number_of_loops, steps))
c) something else

I hope you understand my problem

Thanks,
Thomas

Suppose I have a program, with a class say A and a main.
My program also has a verbose option (program --verbose).
What's the best way to implement the verbose option in a OO-way?

a) give the boolean verbose to the class and let the class control it. (method(verbose) --> puts "something" if verbose)
b) run the program and let the main handle with the verbose option.
c) something else

Hard to say without a little more knowledge of the program and the nature of the class. In general I'd say it depends mostly on how many different places in the code would have different behaviour based on the parameter. In other words, how many places in the code need something like this: "if @verbose then..."

If there's just one place, then it's fine to do it there.

If there's more than one place, then you want to make it one place. One way of doing this is using a logger: the class would *always* tell the logger what's going on, and the logger worries about the verbose parameter and whether or not to tell you. Sort of like this:

class A
   def initialize(verbose = false)
     @logger = Logger.new(verbose)
   end
   def do_something_complicated
     @logger.write("verbose information")
   end
   def do_something_even_more_complicated
     @logger.write("verbose information")
     @logger.write("more verbose information")
   end
end

class Logger
   def initialize(verbose = false)
     @verbose = verbose
   end
   def write(str)
     puts str if @verbose
   end
end

The Logger class in Ruby's stdlib does exactly this, but in a significantly more sophisticated way.

A second question about this is suppose my program runs a loop for a number of times and the user may specify the number of loops to make, and if the program must run to the end in once or ask for user action every x steps)
like: program --loops 50 --steps 5 --> this would ask for user input every 5yt steps and loops 50 times.

What's the best way to do this?

a) again let the class handle it (a method run(number_of_loops, steps))
b) or let the main handle it (in the class just a method step() and in the main the method run(number_of_loops, steps))
c) something else

a) and b) are the same thing, it's just the location of the 'run' method that's different, so the question boils down to "where's the appropraite place to have my 'run' method?" Which is actually quite difficult to answer without knowing anything about the code. Do you think that the 'run' method is integral to the A class? Or is it more of a user-interface thing that should be separate from A? Both approaches could be justified.

matthew smillie.

···

On Jun 19, 2006, at 13:14, thomas coopman wrote:

thomas coopman wrote:

Hi,

I'm verry new to ruby, just use it for some days now and I have question about the best implementation of how to deal with command line options.

Suppose I have a program, with a class say A and a main.
My program also has a verbose option (program --verbose).
What's the best way to implement the verbose option in a OO-way?

These kind of options are often best implemented via global vars. eg.
$VERBOSE. That might seems anti OOP but the reason is that if your
program gets big --ie. spreads across multiple classes, passing such
"universally applicable" options around gets old real qucik.

T.

If there's more than one place, then you want to make it one place.
One way of doing this is using a logger: the class would *always*
tell the logger what's going on, and the logger worries about the
verbose parameter and whether or not to tell you. Sort of like this:

The Logger class in Ruby's stdlib does exactly this, but in a
significantly more sophisticated way.

That's a good idea, I will look into that or else write my own simple logger class

a) and b) are the same thing, it's just the location of the 'run'
method that's different, so the question boils down to "where's the
appropraite place to have my 'run' method?" Which is actually quite
difficult to answer without knowing anything about the code. Do you
think that the 'run' method is integral to the A class? Or is it
more of a user-interface thing that should be separate from A? Both
approaches could be justified.

matthew smillie.

It's indeed a question about where to put the run method, it should probably be placed in the class itself and not in the main.

Another little question, what's the best way to do when writing a program in ruby,
keep the core and the main in different files, place them in the same file,.. or doesn't it matter?

Thanks,

Thomas Coopman

···

On Mon, 19 Jun 2006 22:50:09 +0900 Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

Another little question, what's the best way to do when writing a program in ruby,
keep the core and the main in different files, place them in the same file,.. or doesn't it matter?

To be honest, I'm not 100% sure what you mean by 'main'. I'm guessing it's something like this:

Class A
  ...
end
Class B
  ...
end

# 'main' starts here.
a = A.new
...

In one sense it doesn't matter. But including things like that in the same file can lead to problems if you ever want to use your classes in a different file - your 'main' will get executed when you 'require' the original file. It's likely best in the long run to separate specific programs using your classes from the classes themselves. If you feel like cheating, though, you can always do this:

if $0 == __FILE__
   # main goes in here
end

matthew smillie

Another little question, what's the best way to do when writing a program
in ruby,
keep the core and the main in different files, place them in the same
file,.. or doesn't it matter?

SOC - Separation of Concerns. At least keep them in separate classes. If the
work class is sharable, put it in a separate file or library.

Example:

require 'rubygems'
require 'commandline'

class App < CommandLine::Application
  def initialize
    author "Me, Myself"
    synopsis "[-dhv] file1 file2"
    short_description "...."
    expected_args :file1, :file2
  end

  def main
    MyWorkClass.new(args, opts)
  end
end

class MyWorkClass
  def initialize
    ...
    this class does all the work.
    The command line app is just interface with the user
  end
end

Thanks,

Thomas Coopman

Jim

···

On 6/19/06, thomas coopman <thomas.coopman@gmail.com> wrote:

--
Jim Freeze

Thanks for your answers!

Thomas Coopman

···

On Tue, 20 Jun 2006 00:45:00 +0900 Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

> Another little question, what's the best way to do when writing a
> program in ruby,
> keep the core and the main in different files, place them in the
> same file,.. or doesn't it matter?

To be honest, I'm not 100% sure what you mean by 'main'. I'm
guessing it's something like this:

Class A
  ...
end
Class B
  ...
end

# 'main' starts here.
a = A.new
...

In one sense it doesn't matter. But including things like that in
the same file can lead to problems if you ever want to use your
classes in a different file - your 'main' will get executed when you
'require' the original file. It's likely best in the long run to
separate specific programs using your classes from the classes
themselves. If you feel like cheating, though, you can always do this:

if $0 == __FILE__
   # main goes in here
end

matthew smillie