how do you decide whether to put code in a subroutine or in main portion of a Perl script?

I understand if you need to re-use code you would put it in subroutine, but what if you're not reusing? Is it good practice to put in subroutines to group code and make it easier to read?

Example (in main):

my ($num_one, $num_two) = 1, 2;
print $num_one + $num_two;
print $num_one - $num_two;

Example (in subroutines):

 add($num_one, $num_two);
 subtract($num_one, $num_two);

 sub add {
     my ($num_one, $num_two) = @_;
     return $num_one + $num_two;

 sub subtract {
     my ($num_one, $num_two) = @_;
     return $num_one - $num_two;

I know this is a simple example, but for more complex code (if sub add and sub subtract had more code), would it make sense to group in subroutines?


  • When in doubt, use a subroutine/function. – William Pursell Jun 14 '12 at 15:11
  • Even when you have no doubt, use a subroutine/function. – William Pursell Jun 14 '12 at 15:12
  • 1
    When a code block extends the screen size (about 50 lines), you should start to structure it using sub routines. – ceving Jun 14 '12 at 15:31
  • Someone should have answered just "yes". – Dallaylaen Jun 14 '12 at 17:54

You've pointed out that code is easier to reuse if it's in a subroutine. I think there are at least three other good reasons for using subroutines.

  1. If your subroutines are well-written (by which I mean that they don't use global variables, they have well-defined return points and they are small - certainly no more than a screen-full of code) then you can work on the code in the subroutine without caring about the rest of the code. And that makes your code easier to maintain.
  2. Well-named subroutines make your code easier to follow. If you main line of execution just calls half a dozen well-named subroutines then it is instantly obvious what your program does.
  3. Code in subroutines is far easier to test than code outside of subroutines. Even better if your subroutines are in a separate library. The test suite can just load the library and try each of the subroutines in turn, checking that it has the correct effect.

These points are obviously all simplifications. But they go some way towards explaining why the vast majority of my code is in subroutines.


I'd like to add that using subs adds an element of self-documentation. By creating a three line sub, one can replace

my $sum;
my $count;
for (@levels) {
   next if $_ >= 10;
   $sum += $_;

my $avg = $sum / $count;


my $avg = avg grep $_ >= 10, @levels;

It's much easier to guess what a "avg" does then some loop, and you won't miss the filter in the second version.

Incidentally, this that subs are good for even small pieces of code, and using subs can actually take less code, even if you just call it once! In this case, two fewer non-blank lines.

sub avg {
   my $acc;
   $acc += $_ for @_;
   return $acc / @_;

PS - I avoid putting code at the top level except initialisation code. I put top-level code in blocks to limit the scope of the lexicals and to separate concerns.

   my ($num_one, $num_two) = (1, 2);
   add($num_one, $num_two);
   subtract($num_one, $num_two);
  • use List::Util 'sum'; sub avg { sum(@_) / @_ } is my personal favorite :) – Zaid Jun 14 '12 at 19:32
  • @Zaid, Yes, I would use List::Util too in this case. I guess the lesson is that if you organise your code in terms of basic building blocks (subs), solutions present themselves. :) – ikegami Jun 14 '12 at 19:35

as a general rule, if you're going to repeat a sequence of code more than one time, use a sub. as your script or app grows in complexity you'll take various whacks at refactoring it for logical organization and readability. refine, refine, refine. :)


Yes, it is good practice to break up the program into subroutines even if the subroutine is only called once. because it improves readability. Imagine you have a 'for' loop or an 'if' statement with code inside going over three pages or more .. the logical flow becomes harder to understand. But if you have subroutines (which call other subroutines) - you main loop or main if .. may easily fit on one page - easier to read, easier to maintain.

Also consider that today that code is only being called once, but in 6 months time you may see a need to reuse it - in which case you can simply lift the subroutine.

So yes always use subroutines if possible.

Your Answer

