Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Confused about splitting program into multiple files.

by disciple (Pilgrim)
on Feb 14, 2004 at 23:46 UTC ( [id://329062]=perlquestion: print w/replies, xml ) Need Help??

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

What is the preferred way to write a program (cgi,console - doesn't really matter) and group related functionality into separate files? I have searched PM, and Google; read Learning Perl and Programming Perl and have not yet found an answer. If it is obvious and I have missed it, please forgive me. Let's assume the following:

  • I do not care if I do or do not pollute my namespace.
  • I am not currently doing OO, but I will on another project
  • I was hoping to avoid having to use a package name qualifier and exporting/importing (obviously this does not apply when I am using OO)
  • I want the files to reside in the same directory the main program file resides. Or possibly in a nested directory under that same directory. I cannot install this as a module on the system, I only have limited access to where I can put my files.

I do alot of C# and VB.NET programming, and when I want to include functionality from another file, I simply include the namespace the object resides in. When doing classic ASP, I would simply #include the file containing the functions I want. So what is the preferred method of including functions from other files within the same application?

Thanks,
disciple
  • Comment on Confused about splitting program into multiple files.

Replies are listed 'Best First'.
Re: Confused about splitting program into multiple files.
by davido (Cardinal) on Feb 15, 2004 at 06:43 UTC
    Here is the simplest example I could boil down for you showing how to do exactly what you're asking:

    First, name a file "Mypackage.pm"...

    # Mypackage.pm use strict; use warnings; use base Exporter; our @EXPORT = qw/mysub/; sub mysub { print "It works!\n"; } 1;

    That sets up your module. You may leave it in the same directory as your script, or you can set up a location where you keep all your modules, and follow the instructions in the Camel book on how to let Perl know where to look for it. But in its easiest form, you're just leaving it in the same directory as your script.

    The use base qw/Exporter/; line brings in the necessary behind-the-scenes code to allow you to set up all the tokens (subs, vars, etc) that you wish to make available to your main script. The our @EXPORTER = qw/mysub/; is your opportunity to enumerate exactly which subs and vars you wish to export into global namespace.

    All of that export stuff would be unnecessary if you were willing to just call your subs as "Mypackage::mysub()". But since you're exporting, you can now call them just as "mysub();".

    Oh, and modules always have to return a true value, and that's why the last line of the module is 1;.

    Now your main script can just look like this:

    #!/usr/bin/perl # main script file. use strict; use warnings; use Mypackage; mytest();

    And your output is going to be just what we expect: "It works!"

    I realize that this uses "exporting" to work. But it does so in a way that is pretty invisible to the main script. And asking to export to global namespace without using conventional Exporter techniques is a bit like asking to change a tire without a jack and tire-iron. In this case, it's just "how it's done". And as my example illustrates, it's pretty painless. You don't even have to get grease on your hands.


    Dave

Re: Confused about splitting program into multiple files.
by Anonymous Monk on Feb 14, 2004 at 23:53 UTC

      Thanks. I have read about modules and am aware of that particular method. The concern I have is this. The "module" I will be creating will contain about 40 functions for accessing data from a database. I would like to have all the functions I write to automatically be available instead of explicitly exporting all ~40 of them.

      Should I assume then that there is not another preferred method of doing what I want to do?

      Thanks,
      disciple
        Well "preferred" doesn't really apply, but if you want to do what you are saying, just put "package main;" at the top of the 'module' instead of some other package name.

        Your main program is package main, and by putting your module's subroutines into package main, they are automatically available for you without exporting.

        You probably don't want to here this, but I'll reiterate what the docs and other commenters say. You should really do it the right way and segregate things into separate packages and export only symbols that need to be.

        You're saying the reason you don't want to use a module is because you don't want to copy and paste 40 function names into the @EXPORT array? I'd think you spent more time here trying to find a different way than it would have taken to copy and paste those function names to begin with.
Re: Confused about splitting program into multiple files.
by jeffa (Bishop) on Feb 15, 2004 at 15:55 UTC

    "I cannot install this as a module on the system, I only have limited access to where I can put my files."

    I would like to bring your attention to non-priviledged installations in case you didn't already know that you can install modules on your system. :)

    (updated ... added paragraph)
    Now then. As for exporting ... why do people think that exporting is easier to implement then OO? If you stick with OO methods (that is, you instantiate a class and use it's methods) then you never have to worry about cluttering namespace or getting the Export code correct. Besides, these days you can cheat big time with modules like Class::MethodMaker that "write the code for you." Observe:

    my $dude = new Person; $dude->name('Spicoli'); $dude->age(20); print $dude->as_string, "\n"; package Person; use Class::MethodMaker new => 'new', get_set => [qw(name age)], ; sub as_string { my $self = shift; return $self->name . ' (' . $self->age . ')'; }
    Much nicer. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Ok, here's a question though. What made you choose to

      use Class::MethodMaker;

      instead of

      use base Class::MethodMaker;

      or

      use Class::MethodMaker; our @ISA = qw/Class::MethodMaker/;

      In other words, when should you choose inheritance rather than simple use? The barometer that I've kind of adopted is if I want my object or class to behave as a parent class, inherit. It seems that Class::MethodMaker is one of those cases.

      Please forgive my continued novicity on this subject. ;)


      Dave

        Because i still forget from time to time that one should always "favor aggregation over inheritance." :)

        UPDATE:
        Or am i second guessing myself again? Yes ... never mind my reply, i thought you were referring to something else. (But the concept of aggregation vs. inheritance is still important.)

        My usage simply follows what is illustrated in the POD. There is some syntactical sugar involved, so i don't read into the "useage" too literally -- think of Class::MethodMaker as magic. :)

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: Confused about splitting program into multiple files.
by disciple (Pilgrim) on Feb 15, 2004 at 18:50 UTC

    Thanks everyone for your great responses. So the conclusion is that it is best to explicitly export functions and not put my script in the main package. Either that, or make it an Object.

    Again, I appreciate all your help, especially explaining the reasons behind your recommendations. FYI, Code Complete is an excellent book and I too recommend it to every programmer I know.

    disciple

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-04-19 07:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found