A main() for Perl
In this post, I would like to address the question of a main()
for Perl.
Most Perl scripts don’t have such a subroutine.
Either the Perl script is a module which gets included somewhere else or the script runs standalone and the traditional way will be to just write everything into the global scope:
(Download)
While the above approach is okay, I’d rather have something like this:
(Download)
Note the exit(main())
at the end.
Variables have disappeared from the global scope which usually prevents stupid bugs.
It also forces the developer to be more concise because main-logic cannot be intermingled with non-main-logic like so:
# includes
# some main logic
# more includes
# subroutines
# variable declarations needed for main
# more main logic
# ...
To further enhance encapsulation, consider the following code:
(Download)
The above code effectively converts the script into a Perl package.
This doesn’t have any consequences when using the script standalone because main()
gets executed if no caller exists.
But: We can also treat this script like any normal package and use its defined subroutines etc.
A perfect example would be unit testing:
(Download)
One could argue that foo()
should be defined in a specific package if you want to unit-test it.
While this may be true, there are often situations where it feels copious to do so just for testing.
And here I’m envisioning a scenario where foo()
gets only called by main()
and it thus makes sense to have both in the same package (Main).
I am also usually testing command line options so I code the script in a way that main()
either gets command line arguments provided (unit testing) or reads from the actual command line (Getopt
).
Another useful consequence of this “package-script” approach is the possibility to chain multiple scripts or parts of them. This is a very specific use case but occasionally the end user wants this: “Can I have a script which does A, a script which does B and a script which does A & B together?”. There are obviously other ways to organize the code for this scenario but I in my experiences this approach works very well. It helps to reduce code lines, makes reviewing more easier because the codes sits where you expect it to be.