Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Writing my first module

by harangzsolt33 (Chaplain)
on Aug 30, 2023 at 04:35 UTC ( [id://11154133]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings fellow monks!

I have a bunch of questions about modules. Feel free to answer any of them or all of them. :)

1. Do I need to put "use strict; use warnings;" at the top of my module? I don't see that in other modules, but why?

2. Should I start the perl module with #!/usr/bin/perl or is it okay to leave this off?

3. I think, I am going to write "use MyPackage;" in my perl program, and then myPackage.pm will be placed in my Perl's INC directory. Is this how it should be done? I mean, it works, but is this standard practice? I've seen some people write "require myPackage" but I don't know if I should use that. The difference between "use" and "require" isn't very clear to me. Since "use" is only 3 letters, that's why I thought I am going to use that one instead. lol

4. I've noticed that some modules have "our $VERSION = ..." but I start my module with "my $VERSION" Is that okay?

5. Btw what's the purpose of the $VERSION string? Is there a part of Perl that will try to access that value at some point during my program's execution?

6. What if my module's name conflicts with another module that exists out there? Let's say I call my module something that does not exist in my INC directory yet, but then someone else also creates a module by the same name and it ends up overwriting my module at some point in the future when I download it? How do I prevent this? I want to create a module name that is short and easy to spell, but the problem is that most of the cool names are already taken.

7. What if my module tries to achieve the same result that another popular module does but mine goes about doing it very differently? How should I name my module? My creativity has evaporated. I don't want to give the same name, because that's confusing. Do I make up a random name that has nothing to do with the program? I could call my module bat or ant or eagle, but that's not very descriptive. Lol

8. Is it important to upload a module to CPAN, or can I just put it on my website and host it there? I know, if I die, my website will probably go offline, and CPAN will outlive me. But I still like my website better, because I have full control over it. The CPAN repository seems so convoluted. It's like a big maze to me.

9. When I open some pm files in the INC directory, I notice that a lot of them seem to have plain text mixed with program code. The text or documentation is preceded by something like "=head1 DESCRIPTION" and I am not sure what this is. Is this standard practice? When I read the perl tutorial, I seem to have skipped this part. I don't remember what the "=" sign does. Is it like /* and */ in C language? Is there a program that makes it easy to read these inline documentations?

10. Is it's okay if I put my documentation on simple comment lines started with "#" instead of "=" ?

So, here is what I have so far:

package MyPackage; $VERSION = "1.00"; my $PRIVATE = 444; # # DESCRIPTION: This function is just a test. # USAGE: myFunc() # sub myFunc { $PRIVATE++; print "\nPackage MyPackage::myFunc(@_)\nPRIVATE = $PRIVATE\n"; } 1;

Replies are listed 'Best First'.
Re: Writing my first module
by haukex (Archbishop) on Aug 30, 2023 at 06:58 UTC
    1. Do I need to put "use strict; use warnings;" at the top of my module?

    Yes, Use strict and warnings applies to modules as well. If you see modules not doing that, then likey they are very old and/or not following best practices (or in some modern cases, they may be useing a module that enables them automatically - one example would be use Mojo::Base -strict;).

    2. Should I start the perl module with #!/usr/bin/perl or is it okay to leave this off?

    It's usually fine to leave it off. The shebang's primary use is when executing scripts from the shell on *NIX systems, or for CGI scripts, and since modules typically don't get executed directly, only used, the shebang isn't needed for that. (I did use to have a text editor that used the shebang to detect Perl scripts for its syntax highlighting, so a lot of my modules start with #!perl, but that's usually not needed otherwise.)

    3. I think, I am going to write "use MyPackage;" in my perl program, and then myPackage.pm will be placed in my Perl's INC directory. Is this how it should be done?

    Yes, that's the standard practice. require executes at runtime, while use executes at compile time, meaning that errors will be caught earlier, and also it calls the module's sub import if it has one, so it's the standard way of loading modules. You may also want to look into Exporter to provide the import functionality for you.

    4. I've noticed that some modules have "our $VERSION = ..." but I start my module with "my $VERSION" Is that okay?
    5. Btw what's the purpose of the $VERSION string? Is there a part of Perl that will try to access that value at some point during my program's execution?

    our $VERSION is better, because some Perl utilities need access to the variable (like UNIVERSAL's ->VERSION), and some parse the $VERSION out of modules (like the CPAN indexer, IIRC).

    6. What if my module's name conflicts with another module that exists out there?

    The best thing would be to check the CPAN to avoid such conflicts entirely. But if it can't be avoided - one valid reason might be if you're monkey patching a module - and you don't plan on uploading your module to the CPAN, then the typical way to avoid conflicts on your local machine is to add a directory to @INC where you install the modules, making sure that directory appears first in @INC.

    I notice you wrote "the INC directory" in several places; note there is more than one, and Perl searches them in order for modules, and you can add your own entries to the list in several different ways, e.g. use lib or the PERL5LIB environment variable. And typically, you wouldn't manually place your module into Perl's standard @INC directories, because that's the job of tools like cpanm, so instead you'd add your own directory to @INC so that you can manually modify the contents of that directory without messing up your Perl installation by accident.

    7. What if my module tries to achieve the same result that another popular module does but mine goes about doing it very differently? How should I name my module?

    That depends; if you plan to publish your code to the CPAN then I would recommend you ask for suggestions here by telling us what the modules are and how yours differs (both in functionality and in its API).

    8. Is it important to upload a module to CPAN, or can I just put it on my website and host it there?

    The advantage of the CPAN is that standard tools like cpanm can be used to install modules from there, and as you said, that it is likely to be around for longer. But putting modules on the CPAN does require a bit more work, since you have to put them in a distribution, providing proper documentation, a test suite, a Makefile.PL, and so on. You might want to look at module-starter for that.

    9. When I open some pm files in the INC directory, I notice that a lot of them seem to have plain text mixed with program code. The text or documentation is preceded by something like "=head1 DESCRIPTION" and I am not sure what this is.
    10. Is it's okay if I put my documentation on simple comment lines started with "#" instead of "=" ?

    That's Plain Old Documentation (POD), and is described in perlpod (plus perlpodstyle, perlmodstyle, and perlpodspec). It's much better to use that instead of comments because the standard Perl tools like perldoc will automatically turn that into the nicely-formatted documentation you get when you run perldoc MyModule.pm and when you visit the CPAN website.

    Here's all that applied to your example code:

    package MyPackage; use warnings; use strict; use Exporter 'import'; our @EXPORT_OK = qw/ myFunc /; our $VERSION = "1.00"; =head1 myFunc() This function is just a test. =cut my $PRIVATE = 444; sub myFunc { $PRIVATE++; print "\nPackage MyPackage::myFunc(@_)\nPRIVATE = $PRIVATE\n"; } 1;

    And an example main code, where one quick way you can tell Perl how to find the module is perl -Ipath/to/package script.pl:

    use warnings; use strict; use MyPackage qw/myFunc/; myFunc();
      Wow, thank you so much for answering all my questions so quickly and in such great detail!!!

      I have one more question. I guess, I can look this up myself. My assumption is if the shebang is not mandatory for pm files in Linux (because pm files are not meant to be executed from command line), then I guess the file's permissions can be 644. They are not required to be 755. Correct?

        My assumption is if the shebang is not mandatory for pm files in Linux (because pm files are not meant to be executed from command line), then I guess the file's permissions can be 644. They are not required to be 755.

        Yes. For cheap thrills, I ran these commands on my recently installed perl 5.38 on Ubuntu:

        ~/localperl$ find . -name '*.pm' -ls >pm.tmp ~/localperl$ find . -name '*.pl' -ls >pl.tmp

        All the .pm files have permissions like this:

        -r--r--r-- ... ./lib/5.38.0/Carp.pm

        The perl commands in the bin directory designed to be run as commands have permissions like this example of the prove command:

        -rwxr-xr-x ... prove

        These text files also tend to start with a shebang line like:

        #!/home/youruser/localperl/bin/perl

        There are also plenty of .pl files lying around with permissions like this:

        -r--r--r-- ... somefile.pl
        which is fine because you can still run them manually via:
        perl /somepath/somefile.pl

        My assumption is if the shebang is not mandatory for pm files in Linux (because pm files are not meant to be executed from command line), then I guess the file's permissions can be 644. They are not required to be 755. Correct?

        Yes!

        I came back - my back is hurting and couldn't sleep....

        There is one trick that I sometimes use....
        It is possible for your module to know if it was "used" versus executed directly. This allows me to put a test driver in the module itself that I use during development that presents more info that just a "pass/fail". If you do this, you will want your .pm to be an executable file under Unix.

        #Normal module preamble here... sub test{ print "this is a dev test...\n"; } test() if not caller; ### Run test() if run directly #Normal rest of module code here.... 1;

      Also for #1 where something else enables them, use can implicitly enable strict or warnings depending on the version.

      See use VERSION

Re: Writing my first module
by Discipulus (Canon) on Aug 30, 2023 at 07:39 UTC
    Hello harangzsolt33,

    you alredy had very good replies so I can just add few cents.. for example you might like to browse some link in my bibliotheca

    No one mentioned something very important: tests! In my opinion good software consists of 3 ingredients: code, tests and documentation. No one of these 3 can be poor to have a nice resulting recipit.

    You can also take a look to my step-by-step-tutorial-on-perl-module-creation-with-tests-and-git.

    Share the code soon and consider also a visit to prepan.org. (see below)

    Have fun!

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      Thank you for the resources! Now I have plenty to read.

      Btw prepan.org seems to be about computer programming, but it's all written in Chinese. Is that the correct link?

        ..oops sorry if I didnt checked :( goodbye-prepan

        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Writing my first module
by eyepopslikeamosquito (Archbishop) on Aug 30, 2023 at 07:41 UTC

    haukex has already provided mind-bogglingly excellent answers to each of your ten questions. As a starting point, I suggest you start with his sample MyPackage given at the end of his reply, and then gradually flesh it out, learning as you go. Feel free to post early versions here for feedback.

    As time permits, you might also like to browse through my humungous Writing Solid CPAN Modules looking for any topics that you have a special interest in.

    I still remember the steep learning curve when writing my first Perl module. Lots to learn, but very rewarding. Good luck with your first Perl module!

      Lots of good info! Thank you very much!!
Re: Writing my first module
by Marshall (Canon) on Aug 30, 2023 at 06:58 UTC
    First of all, I would recommend the Monk's tutorial on Modules: Modules-How-to-Create-Install-and-Use Read through that and then tell us what questions remain. Sorry I don't have time at the moment to make detailed question by question responses.

    Are you writing a module for your own use or are you planning on releasing a module on CPAN for use by others? Doing the former is easier and I would recommend doing that before trying to make a module release.

      Yes, I am planning to write the module for personal use first. And if it seems to be useful and work without any glitches and I can write the documentation for it, I may release it on my website... and maybe CPAN as well. The latter one seems to be a lot of extra work, but I will study the link you posted. Thank you!
Re: Writing my first module
by karlgoethebier (Abbot) on Aug 30, 2023 at 09:01 UTC
Re: Writing my first module
by choroba (Cardinal) on Aug 30, 2023 at 22:04 UTC
    > I am going to write "use MyPackage;" in my perl program, and then myPackage.pm will be placed in my Perl's INC directory.

    Just a nitpick: the case is important. On some systems (e.g. linux), MyPackage.pm and myPackage.pm can be two files coexisting in the same directory.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Log In?
Username:
Password:

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

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

    No recent polls found