http://qs321.pair.com?node_id=139200


in reply to Re: Re: Re: Command line tool coding style?
in thread Command line tool coding style?

I actually agree it is sort of JAPHish - that's why I posted it as a question here. I went through thinking about a dispatch table exactly the way you proposed, as I already explained in my reply to chromatic, but it has the same problem as the switch-construct: adding an "action handler" requires maintaining the dispatch table. I could have put the handlers as anonymous subs right into the dispatch table, but then I have to define them before the body of the main program and they're very long. (The biggest one is 2.5 pages of straight-through code without any loops.)

I sort of like your eval proposition, though the idea of circumventing strict in whichever fashion irks me. :-)

Thinking about it some more I think the sole reason it turns JAPHish is the role I have given to new() - that's the single thing I would point out as contrived in retrospect. I wonder if it's possible (and what you'd think) of doing something along the following lines:

#!/usr/bin/perl use warnings; use strict; print "\nfoo script\n\n"; my $action = shift(@ARGV); die "Usage here\n" unless $action; my $handler = can main "_$action"; die "Unknown action '$action'\n\nUsage here\n" unless ref $handler; my %params; GetOptions(\%params, qw(various options here)); # do more stuff with %params here $handler->(\%params); exit; ###################################################################### +## ###################################################################### +## use Getopt::Long; # use Other::Modules::Here; # .. etc ..

Replies are listed 'Best First'.
Re: Re: Re: Re: Re: Command line tool coding style?
by perrin (Chancellor) on Jan 16, 2002 at 23:10 UTC
    I'd suggest moving the "use Getopt::Long" to the top part, since that's where you actually use the module, and giving the lower section a real package name ("package MyTool" or something). Then instead of this:
    my $handler = can main "_$action";
    you can have this: this:
    my $handler = MyTool->can("_$action");
    Easier to follow, in my opinion.

    Incidentally, a nice way to code tools like this is to make a separate module that implements all of the real logic, and then a CLI wrapper that just calls that module's methods. Then you can easilly add a GUI, call it from CGI, etc.

      Ops, forgot to move the Getopt::Long when I restructured the code - of course it belongs at the top.

      Good point about the extra package as well - I had a package Logic; and package Utils; at first, but it made the code in Logic awfully bulky if I didn't import all the utility functions. Now that I have a naming convention for the handlers it is quite effortlessly possible to use a package once again - handlers and utility functions can be distinguished quite easily. What's left in main is just the initialization skeleton then.

      I'm well aware of the points to be made for proper modularization (I tend to modularize too much actually - one of them hubris people is me, not a lazy one).

      It is obviously necessary to always remember under which premises one took certain decisions and to go back and reassert them as one simplifies one's code. Thanks for helping me find the proper way. :-)