Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: when to use subroutine

by brian_d_foy (Abbot)
on Oct 28, 2007 at 17:56 UTC ( [id://647717]=note: print w/replies, xml ) Need Help??


in reply to when to use subroutine

There isn't any hard rule (meaning something that everyone will agree on and everyone uses across all situations). Often the aswer depends on real-world factors such as "do I really care since this is a one page script" and "What's on TV tonight?". For anything that is going to be part of something that lives beyond next week, I generally start with subroutines instead of switching to them later.

Subroutines give names to logical tasks. Instead of typing out a bunch of code "inline", you use the name instead. You don't really care about how the work gets done as long as it gets done. When the implementation hides behind the subroutine name, it doesn't clutter the flow of your program, and if you decide to change it later, the program doesn't really care (unless you're changing the argument order or return values somehow). When people read your program, they see the concepts and ideas rather than the mechanics:

########### # Here's what this program does: my $data = read_data(); my @records = extract_records( $data ); my @answers = do_calculations( @records ); print_results( @answers ); ########### # Here's how this program does it: sub read_data { ... lots of distracting code ... } sub extract_records { ... more distracting code ... } sub do_calculations { ... this stuff is complicated ... }

Some people will tell you to "refactor" code into a subroutine when you start using it in multiple places in your program. That's fine, and you'll see some of this in How a script becomes a module. You code up a little bit of code to do something, and realize that you need to do the same thing somewhere else so you copy and paste, Then you need it somewhere else, so you move it into a subroutine. That works okay, but after a while you figure out that you do that so often that you might as well just start with a subroutine.

Another rule is to keep any section of code short; not as short as possible (this isn't golf), but not longer than it needs to be. Like the example before, the idea is to show the concept and not the mechanics. When your while loop starts to spill off the screen, move some of it's code into a subroutine. The loop takes up fewer lines and you get a shorter block of code. That's easier to read and understand. Inside your subroutines you do that same thing: when they get too long, break them up.

When you break up code into subroutines, you want to "decouple" that code. Subroutines only know what you tell them by passing them data. They don't look inside global variables or try to figure out the state of the larger task. They do their bit and give a result. Since you've decoupled and isolated that code, you don't have weird "action at a distance" bugs, and it's a lot easier to test your subroutines (another benefit of everything in subs).

Now, inside the subroutines, you really only want to do one thing. I'm not going to say what that one thing is, but the idea is that subroutines should be short and well defined. The one thing is does is a logical task, and maybe that logical task is really several implementation steps. Those implementation steps are sub-tasks which probably belong in their own subroutines. Now, despite your question about knowing where the line is, you'll get used to where the line between inlining and subroutining is by simply programming for a bit. You don't want a couple giant subroutines, but you don't want 10,000 subroutines all doing trivial things.

Good luck :)

Oh, and some books that might give you a better feel for programming, even if they don't directly answer this question: The Pragmatic Programmer, The Practice of Programming, and Refactoring. There are probably plenty of other books too, but looking at my shelf right now that's what I see.

--
brian d foy <brian@stonehenge.com>
Subscribe to The Perl Review

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://647717]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-03-29 11:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found