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

Hello Monks,

     Through a serious of events that I am sure no one here at the monestary wants to here, a program that I use often got deleted. This actually comes as a blessing in disguise since the code was fairly messy(It was my first perl program that actually did anything of use for me). I was laying out a basic template for the structure of the program and stumbled upon a question. When is it appropriate separate code into packages and subroutines? Should you only put something into a subroutine if it is code that is used multiple times?

Readmore to see the template I have created and more detailed description of my question.

Here is the template for the program I am creating:
#!perl #RunLogger2 v0.001 use warnings; use diagnostics; use strict; use PassMasker; #####User Interface##### sub login{} sub login_parser{} sub menu{} sub menu_parser{} ###Data Checking### sub check_date{} ###DataBase Interface### { package Runner; sub new{} sub ran{} sub edit_run{} sub edit_runner{} sub print_log{} }

     PassMasker is a module I created which contains a fairly simple subroutine which allows a password to be given by the user, but only stars(or any choosen mask) will show up on the screen. (See this node if you are interested in it)

     Now to the questions. I felt it was a good idea to separate the code dealing with the user interface from the code dealing with the database. Futhermore, I have given the interface to the a separate package. I did this becuase I think it will improve maintainability,since I would be able to seperate problems caused by my communication with the database I am using(probably a plain DBM file) from problems caused by my communcation with the user. However I am very new to perl and programming, and am not sure if this is the best way to proceed. Am I simply adding more complication becuase of the comminication between the different subroutines and if some of these subroutines are only used once is this just a waste of space? To give an example:

The subroutine Runner::new will probably only be used once during the program. Would it be better to simply put that code directly into Main::menu_parser, which will determine which subroutine to call based on the user input?

As I am typing this, I am realizing the exact meaning of what I am asking may be ambiguous without code to show what would be going on in each sub. Here is an attempt to pose a more general question:

Is there merit in sub-dividing code into packages/subroutines even if it is not syntactically needed?

I feel that if I am ever going to learn to program well I need to start making clean, managable code. Any suggestion on this topic would be very helpful, so I can at least be headed in the right direction before I start the more major coding.

Thanks in Advance.

  • Comment on When Is Dividing Code Into Different Subroutines/Packages Important?
  • Download Code

Replies are listed 'Best First'.
Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by chromatic (Archbishop) on Jun 14, 2003 at 06:28 UTC
    Is there merit in sub-dividing code into packages/subroutines even if it is not syntactically needed?

    Surprisingly little is syntactically necessary. If you want to be pedantic, you really only need to fetch and store bits in memory and do a couple of comparisons.

    The nice things about subroutines and packages is that they give you, the programmer, short names for things. You could write:

    sub main { # read arguments ... # process arguments ... # open a file ... # process the file ... # open output file ... # write output file ... # clean up temporary files ... # exit }

    That's a perfectly valid program. It might be the best program to write for your circumstance. It's nice that the comments are there. Look what happens when you use subroutines though:

    sub main { my %args = read_arguments(); process_args( \%args ); my $file = open_file( \%args ); my $data = process_file( $file, \%args ); write_output( $data, \%args ); cleanup( $file, \%args ); }

    The compiler doesn't care about the names. The computer really doesn't care about the names. They make quite a difference to me though.

    I know which program I'd rather maintain.

Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by meredith (Friar) on Jun 14, 2003 at 03:32 UTC
    I use packages and break out into subs for two major reasons: maintainability and reuse.

    That way, I can break out items that I use often, as you have done with PassMaster, and have a single place to fix bugs. Imagine if you had used PassMaster instead as simply a cut and paste snippet, and put it in some 12 scripts. Then, later along, you realize that the masking becomes ineffective if the user sends a certain excape sequence! Sure, fixing 12 scripts can be done, but we're lazy, aren't we? Yes.

    I also tend to start my projects by starting a bit on each major component, and put things into packages as I go. That way, if I realize that I've already written something, all I have to do is use it. Boy am I making things easy for myself ;)

    When done right, using subs and packages also makes it easy to expand your code, or refactor it (to an extent). If you haven't noticed the real point yet, it's all about making things easier on you. It's just a little effort for a big payoff.

    P.S.: I don't believe you need the brackets in the DataBase Interface section -- the package statement applies until the next package or end of file. diagnostics should probably left out when the code goes to production, too. :)

    Update: Oh also, ++ for the question! I expect some great responses coming soon!

    mhoward - at - hattmoward.org
Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by jepri (Parson) on Jun 14, 2003 at 13:35 UTC
    Is there merit in sub-dividing code into packages/subroutines even if it is not syntactically needed?

    Oh yes indeedy. Not only does breaking your code into subs enhance usability, promote code reuse, get your whites whiter and make your code smell fresher, it also helps you catch screw ups.

    Breaking code into subs gives you more protection against errors. If you fumble and put one too many '}' characters into your code, you can locate it faster. And it eliminates one of my most popular screw-ups: using the wrong temporary variable by mistake.

    #Convert latitude and longitude to DMS and save $lat = getlat(); convert(\$lat); #Cut and paste goes horribly wrong $long = getlat(); convert(\$lat); print FH "Lat: $lat, Long: $long\n";

    I actually did that once. Now if I had code that looked like:

    print FH "Lat: ", convert_lat(), " Long: ", convert_long(), "\n";

    then I couldn't have got confused - I wouldn't be able to accidently use the wrong variable.

    There was at one time a fad for having no routine longer than 7 lines (or 9 lines, or 13).You can take that to extremes (creating thousands of 7-line functions is obviously silly) but it's not a terrible thing to try for, so long as you know when to break it. I tend to arrange big code blocks into paragraphs of 5-10 lines, it seems natural to me.

    The concept was based on some urban legend about the brain only being able to concentrate on 7 things at a time. That might even be true, but I don't see how it translates to 7 lines.

    And as others have mentioned, you can change those subroutines a lot more easily than editing some lines buried in the middle of a large chunk of code.

    I didn't believe in evil until I dated it.

      That thing about not making a sub more than X lines has nothing to do with the brain. It's just something computer-sciences teachers do to make you learn how to divide your code into paragraphs acording to its use instead of writing long unreadable "spaghety code" (that's what we called complicated code back in the days of BASIC...)
Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by yosefm (Friar) on Jun 14, 2003 at 10:26 UTC
    It seems like your code is just the right thing.

    Generaly, anything that could be useful to other programs should be seperated into a module even if currently you use it only once. A good example is the function login().

    similarly some snippets of code, even if only used once should be separated into functions if they do something useful. Beside helping readability, this gives you the ability to reuse in the future.

    Say you used the login process only once, making the program die on login failure. Now you improve your program and you want to allow 3 trials, or allow the user to use your program anonimously and login only for certain features etc. Are you gonna re-write the login snippet of code? or transfer it to a function? Better to put it in a function in the first place.

    It's like filing your bills when you get them instead of stocking a big pile and have lots of fun sorting them at the end of the year.

(jeffa) Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by jeffa (Bishop) on Jun 14, 2003 at 13:56 UTC
    When? When you have to maintain that code, especially when others have to maintain that code. Of course, merely using subs and packages does not guarantee robust, reusable code, but when working on team with others, proper decomposition (and a good API) is a must.


    (the triplet paradiddle with high-hat)
Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by markjugg (Curate) on Jun 14, 2003 at 17:52 UTC
    You might also be interested in the book "Code Complete". It has a section on appropriate organization code. It also contains lots of other good suggestions for effective programming practices.


      I will look for it the next time I am at the library (what can I say, I am a cheap teen who spends all his money on gas), thanks for the suggestion.
Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by Missing Words (Scribe) on Jun 14, 2003 at 15:41 UTC
    Much Thanks for the help.

    Much of it confirms what I had thought after reviewing code around the monestary for the last few days; however, it is always nice for a newbie like me to have a little reassurence that I am heading in the right direction.
      There is allways a need of testing some part of your code.

      So, you can group some parts to test alone. This is also a reason for having some code separated.

      If you think some code is not going to stay like it is for a long time, by having it at a subrutine, you ensure that everything that is related to it goes modified even if you forget what was all about.

      The correct way of structuring some code, IMHO, is by starting keeping as much as you can together.

      Then with the use, you are going to notice the risk of keeping all in this way, and you are going to happily start cutting some code and making some standarization for future improvement.

Re: When Is Dividing Code Into Different Subroutines/Packages Important?
by Cody Pendant (Prior) on Jun 16, 2003 at 01:09 UTC
    I recently had to update some website code which accessed a certain directory to get flat files. I needed to change to a different directory. That directory location was hard-coded into three different scripts.

    It only took me a minute or two to update and save all three files, but as it was a web application, a minute or two could have meant quite a few errors because of the discrepancy between what script A was reading and what script B was reading.

    Only a small thing, but I was forcefully reminded that if I wanted to do a cutover like that from one file system to another, it would get done much more cleanly if the directory location could be changed in only one file, so I put it into a shared "require" file ASAP.

    “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.”
    M-J D
      Let's go even further: Never hard-code anything, except when it's:
      • A constant at the top of you'r script, so it's easy to find
      • or, better yet, in a different file shared by all scripts in your app, if you have more than one.