run() module, run()

Eric Wilhelm scratchcomputing at gmail.com
Sat Feb 17 18:06:58 GMT 2007


# from Edmund von der Burg
# on Saturday 17 February 2007 05:21 am:

>This would be comprised of a core module that deals with parsing the
>command line arguments and then hands over to plugins to do the actual
>work. The actual script would just 'use' the core module and then call
>its 'run' method.

I agree that code should be modularized, but I have to say that I'm not 
a fan of this Module->run() architectural style.  I think it leads to 
inflexible code because too much functionality gets balled-up into one 
place.

While I haven't exactly nailed-down a theory of modularizable, testable 
script style, I have been working in that direction for a while now.  
So, take the following as half-baked or whatever, but I do think the 
run() scheme has a lot of room for improvement -- particularly in 
agility and reuse.

The run() scheme can be tolerable IFF your code is broken into App::CLI 
style modules, but sometimes that seems a bit heavy, particularly when 
a project is first taking shape.

With a single module designed to be entered from a single run() method, 
I think too much of what wants to be in the program ends up in the 
module.  At that point, why have a module?  Just to be able to test it?  
I don't think this justifies it, as testing a properly structured 
program is just like testing a module.

I want module API's to be made of small parts, with at least 
contructors, aliases/dispatch, options, and arguments handled in the 
frontend program code.

What happens when you (or another programmer) need to put a second 
frontend on the module?  Does it need a run2 method?  Or, does the 
other programmer need to copy and paste the argument processing done in 
run() to replicate the functionality.  I think the run() method can 
easily become too difficult to refactor.

What about aliased commands?  Does Module->run() check $0?  What about 
command-line arguments?  Does Module->run() check @ARGV (or call 
GetOptions(), which checks @ARGV.)  I think having program-specific 
globals in a module can easily make it difficult to trace.  Plus, that 
code is going to naturally tend away from flexibility rather than 
toward it.

Some examples of my recent style:

* no module, no functions, everything in bin::famwatch::main()
http://scratchcomputing.com/svn/misc/trunk/code/perl/bin/famwatch

* same as above, but with a CPAN module
http://scratchcomputing.com/svn/wx_hacks/trunk/code/perl/bin/wxdo

* module, dispatcher, still in one file
http://scratchcomputing.com/svn/code_utilities/trunk/code/perl/bin/podadz

* module, dispatcher, multiple files
http://scratchcomputing.com/svn/App-YmlDB/trunk/bin/ymldb

--Eric
-- 
[...proprietary software is better than gpl because...] "There is value
in having somebody you can write checks to, and they fix bugs."
--Mike McNamara (president of a commercial software company)
---------------------------------------------------
    http://scratchcomputing.com
---------------------------------------------------


More information about the london.pm mailing list