Alex
Alex

Reputation: 749

Code in main vs subroutine

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):

 my ($num_one, $num_two) = 1, 2;
 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?

Thanks!

Upvotes: 3

Views: 2160

Answers (4)

Dave Cross
Dave Cross

Reputation: 69294

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 your 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.

Upvotes: 5

ikegami
ikegami

Reputation: 385976

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;
   ++$count;
   $sum += $_;
}

my $avg = $sum / $count;

with

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

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

Incidentally, 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);
}

Upvotes: 5

Tenakha
Tenakha

Reputation: 183

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.

Upvotes: 2

shinronin
shinronin

Reputation: 193

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. :)

Upvotes: 2

Related Questions