Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Subroutines versus straight top to bottom scripts

by ghenry (Vicar)
on Jun 03, 2005 at 09:05 UTC ( [id://463180]=perlquestion: print w/replies, xml ) Need Help??

ghenry has asked for the wisdom of the Perl Monks concerning the following question:

Dear Master Monks,

In the most basic sense, would there be any other benefits, other than reusability, when creating a script that is almost all subroutines, with them being called one after the other, against just writing a top to bottom script?

Walking the road to enlightenment... I found a penguin and a camel on the way.....
Fancy a yourname@perl.me.uk? Just ask!!!
  • Comment on Subroutines versus straight top to bottom scripts

Replies are listed 'Best First'.
Re: Subroutines versus straight top to bottom scripts
by demerphq (Chancellor) on Jun 03, 2005 at 09:17 UTC

    Maintainability generally. Comprehension improves when information is in chunks that map onto an abstract model of what the process is doing. Its much easier to understand a program where dataflow only happens by argument passing and where subroutines are as minimalistic as is reasonably possible. Even when your script is pretty well unreusable its a lot easier to extend and maintain if you can ignore large chunks of the code because they are in subroutines clearly named as not being relevent to the issue at hand.

    For instance lets say we have a program that scans a bunch of files and generates some stats. We could put the whole process into a single sub or not even use one, but it would be a lot easier to understand if we could just look at main and see what it does:

    sub main { my @files=get_files(...); my $stats=scan_files(\@files); print_stats($stats); return 0; } exit(main());

    ---
    $world=~s/war/peace/g

      I understand your point. I have myself a further problem : I write quite big applications (several -- up to 50 -- thousand lines). A typical program have hundreds of subs. Some subs are only called from other subs, which are called by other subs, .... which are called from main. How would you split that? Should I write a different package for each "big enough" sub?
        That depends entirely on the circumstances and what all the subs do. If, for example, you have a group of subs that all do one thing or another with a given set of data, then it could be worth the trouble to turn said set of data into an object and treat the subs that go along with it as methods but once again, that depends entirely on the context within which one is working. I myself almost exclusively use OO style perl but that just so happens to be because the things I generally work with can easily be translated to an OO style of thinking. Could you elaborate a bit on what kind of subroutines we're talking about?


        Remember rule one...
        I have constructed my programs so that they consist of a main() sub which made up of a list of smaller subroutines.
        Each line of the main() is commented.

        The effect is similar to a novel with the main equivalent to a list of chapters with the sub routines making up like the contents of a book.

        Also when I need to check any part of the program I can see in the main where about it is
        and can quickly "find" to the sub.

        Making changes updating or removing is made alot easier especially when there are no inner subroutines.

        Of course not all the sub routines are listed in main() as some are within called with others

Re: Subroutines versus straight top to bottom scripts
by erix (Prior) on Jun 03, 2005 at 09:20 UTC

    How about comprehensibility?

    Subroutines as short as possible; hopefully never longer than what fits on screen. Smaller is better ( < 20-25 lines?).

    With subroutines, testing becomes easier or even feasible.

    (And yes, reusability: you'll end up with subs anyway, if the script will have any life beyond running once.)

      reading your comment I become curious about how many lines I put on my subs and wrote this little script: counting the lines on your subs.

      Running it over my code I have found that most of my subs are below 10 lines, and the most frequent size is 1 line (~18%), even when I use mcoder or Class::MethodMaker to generate common accessors that are not counted!

      While my subroutines tend to be short, actual data on benefits of short subroutines is more ambiguous. In fact there is some data saying that short subroutines are counterproductive. Obviously this doesn't match widely held current beliefs. See Short routines matter more in OO? for some guesses as to why this might be.
Re: Subroutines versus straight top to bottom scripts
by spurperl (Priest) on Jun 03, 2005 at 09:25 UTC
    The reusability comes on two levels - in-script, and inter-script. In-script means that you might want to do the same thing several times in your script, and subroutines would be useful for that. Inter-script means that you can reuse some of this script's code for that script.

    So yes, subroutines greatly aid reusability, on both levels.

    Additionally, subs are easier to test than a top-down script. You only have to extensively test one sub at a time - once it's clean, you're confident to use it. Writin unit test is also simpler for subroutines with well defined interfaces than for whole scripts.

Re: Subroutines versus straight top to bottom scripts
by salva (Canon) on Jun 03, 2005 at 09:35 UTC
    code structured in subroutines is usually much easier to understand, maintain and test:

    On a top to botton script high level and low level ideas get "mixed" and even if it is commented, you have to read it fully to understand what it does.

    Discovering which data is input and output for a particular step can also be a hard task because variables can be referenced in any place. On the other hand, when using subroutines, seen what is input and output in every step is trivial, you only have to look at the glue code between the subroutine calls.

    Other problem that sometimes appear, is naming temporary vars, specially because we always try to use common names like $len, $i, $j. You have to take care to use different ones on every step or to ensure that you can reuse them without trouble or to open new scopes. When using subroutines this problem just go away.

Re: Subroutines versus straight top to bottom scripts
by perl_devel (Friar) on Jun 03, 2005 at 10:28 UTC
    Apart from readability and reusability Debugging becomes most easier when Big block of codes are split up in to junks of building blocks. Because we have debugging tools which tells which method has raised the bug, Just think of caller as an eg which tells which method has invoked.
    Regards
    P.B.Sathish Kumar
Code Complete
by schwern (Scribe) on Jun 04, 2005 at 06:08 UTC

    "Code Complete 2" has an entire chapter (#7) on subroutines. Why to make them. How to design them, name them. How long they should be. What parameters they should take. I would highly suggest reading that, even if its just pulling it off the shelf at your local Super Mega Book Store.

    But the way I've always thought about subroutines is NOT in terms of reuse. Equating subroutines with reuse is the great downfall of many a new programmer. When you write out your code you often have no idea what is or is not going to be reused. No, subroutines are for something far more important: encapsulation. Limiting what you have to know and how wide an effect a change can have.

    In much the same way as a book is broken down into chapters, sections and paragraphs, your code should be broken down into modules, libraries and routines. Why? Because trying to understand a bunch of information smashed together sucks. Subroutines, like paragraphs, let you know where one idea begins and ends. They allow you to skip around within the code. When well named, they allow you to know what the routine does without having to read all the details allowing you to skim.

    Routines provide a beginning and an end of scope. Scope for variables. This limits just how much information you need to keep in your head at once. To understand a routine you need to keep in mind A) the variables passed in B) the variables local to the routine C) the (hopefully very few) globals used. When reading a blob of code you have to keep in mind nearly all possible variables because any one could be used at any moment. Since there is no structure any given line of code could manipulate any given piece of data.

    Routines also make testing and documentation much, much easier. Its easy to document something that does one thing rather than something that does a dozen. Its also much easier to test. Once you've got a solid foundation of tested routines figuring out what went wrong when you combine them becomes easier. You know the routine works, it must be something about the integration code. Again, limiting the scope of what you need to worry about.

    And finally to reuse. Its difficult to know up front what i s and is not going to be reused. Reuse is something which is discovered. When your code is written in one big blob its difficult to see what parts can be made into reusable widgets. Its also a lot of work to extract the reusable bits, especially after they've been hacked on, so you're less likely to redesign a hunk of code into a reusable routine than to just cut & paste. When you write out each logical chunk as a routine as you go the pieces are evident and there for the taking. The borders are well defined so you will be less likely to tangle them up in the course of maintaining the code. The code will then actually get reused.

Re: Subroutines versus straight top to bottom scripts
by mattr (Curate) on Jun 03, 2005 at 15:40 UTC
    Just to add a couple more cents.. I used to like CodeWarrior (well except when it crashed) because it had a widget to collapse subroutines. In fact I would love it if someone could tell me to do that in XEmacs. Anyway, you can reuse the subroutines in other apps later if you write them sanely, and you can collapse them or move them to another file to require, or into a module, and it becomes much easier to navigate to where you want to go to find something. Especially with perl I find lack of clutter on the screen helps me to keep my brain uncluttered too, YMMV.

      I had a thread on cross-platform editors a while back. I always like Emacs, but had gotten away from it because of it's lack of code-folding (which is what you're talking about). However, a respondant to my query replied with information about an Emacs LISP file that adds code-folding. I'm using Eclipse now, so I haven't run the ELISP referenced, but it is here: Re: Cross-platform development: editors

      Yoda would agree with Perl design: there is no try{}

        I just looked at the folding.el mentioned in that other thread and it mentioned that imenu (included with Emacs) and hideshow might be good packages for function/block-level hiding. The former is interesting, and I didn't know about it, but it doesn't provide hiding capability. I just tried out the latter and it seems good so far at hiding blocks.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://463180]
Approved by Joost
Front-paged by tlm
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2024-04-24 21:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found