Moving towards modularity
●Programming in its simplest form is writing lines of code that execute sequentially:
●
● #!/usr/bin/perl
● use warnings;
● use strict;
●
● my $name = “Dan”;
● print “Hello $name!\n”;
●
● #prints Hello Dan!
Moving towards modularity
• Writing line by line code works fine for people learning to code but the paradigm quickly breaks down when we have to repeat tasks:
•
– #!/usr/bin/perl –
– use warnings;
– use strict;
– my $name1 = “Dan”;
– print “Hello $name1!\n”;
– my $name2 = “Tim”;
– print “Hello $name2!\n”;
– my $name3 = “Joe”;
– print “Hello $name3!\n”;
Moving towards modularity
• Problems start when we need to rewrite our code. Lets say our French colleagues want a version of our software. 3 lines of code need
altering!
– #!/usr/bin/perl –
– use warnings;
– use strict;
– my $name1 = “Dan”;
– print “Bonjnour $name1!\n”;
– my $name2 = “Tim”;
– print “Bonjour $name2!\n”;
– my $name3 = “Joe”;
– print “Bonjour $name3!\n”;
Moving towards modularity
• It's much better to encapsulate repetitive tasks into subroutines:
– #!/usr/bin/perl –
– use warnings;
– use strict;
–
– sub greet {
• print “Hello $_[0]\n”;
– }
– my $name = “Dan”;
– greet($name);
– my $name1 = “Tim”;
– greet($name1);
Moving towards modularity
• Now to change the entire code into French, we change a single line:
– #!/usr/bin/perl –
– use warnings;
– use strict;
–
– sub greet {
• print “Bonjour $_[0]\n”;
– }
– my $name = “Dan”;
– greet($name);
– my $name1 = “Tim”;
– greet($name1);
NB: Indexed Scalars
• You may be wondering what $_[0] means.
• When a subroutine is called any parameters that are passed to the subroutine are passed as a list in the special array : @_
• Just like any other list array the individual elements of @_ can be accessed with the square bracket notation
• $_[0] is the first element of the @_ array
• $_[1] is the second element of the @_ array
• Hence in our previous example we are passing “Dan” and “Tim” as
elements of the @_ array to the subroutine greet and printing accessing them as $_[0]
Moving towards modularity
• We can now use the greet() subroutine anywhere in the program, making the code shorter, easier to read and easier to maintain
• What happens if we like the greet() subroutine so much that we want to use it in another program we have written?
• The beginner programmer simply copies and pastes the subroutine in from the other program.
• What is the problem with this?
• The problem is that if we make enhancements to greet() in one bit of code, we have to make it in ALL other copies of code it has been spread to.
• The smart programmer incorporates greet() into a module.
What is a module?
• A module is a library of Perl code that can be included in your Perl program.
• When you “include” a a Perl module in a program, the functionality of that module is available for you to use inside that program.
• In our example that means every program we write would be able to use our greet() subroutine.
• Code reuse is a good thing!
Where do we get modules?
• Perl modules come from a variety of sources.
• Standard modules – these come with Perl. They are effectively pre
installed.
• CPAN – Comprehensive Perl Archive Network – a global network of Perl modules
• Third party – you write them yourself or they are “inhouse” code libraries or they are neither from the Perl installation or from CPAN.
How to use a module
• In order to include a module in a program you use Perl's use keyword.
• The general form for this is:
– use Module;
• Typically the module will then export its most popular subroutines and variables into your program.
• You can then use these subroutines and variables just as if they were declared in your program.
• Of course we are all really familiar with module use anyway as we:
– use warnings;
– use strict;
How to use a module
• For example, if we had created a module called Hello.pm (the .pm suffix normally denotes a Perl module) that contained our greet() subroutine we could then write this:
– #!/usr/bin/perl
–
– use warnings;
– use strict;
– use Hello; #use the Hello module –
– greet (“Dan”); #greet() is exported – greet (“Tim”); #by the Hello module
How to use a module
• Not all subroutines/variables in a module are exported by default. To use nondefault aspects of a module you precede their name with the module name followed by a double colon ::
•
– #!/usr/bin/perl –
– use warnings;
– use strict;
–
– Hello::greet(“Dan”);
– #calls greet() from the Hello module
–
How to use a module
• Alternatively, you can state explicitly which variables and subroutines you want to to export from the module using the following form:
•
– use Module qw( $variable, subroutine );
–
• In this case $variable and subroutine are the items you want to export from the module to your own code.
• Using this syntax overrides the default form – only the variables and subroutines you specify are imported into your code!
•
Example module: Text::Wrap
• Text::Wrap is a very simple to use, but very useful module. It's a standard module, which means it is installed when you install Perl.
• Text::Wrap contains a subroutine called wrap().
• wrap() is exported by default and its function is to take a chunk of unformatted text and makes neat paragraphs with it.
• wrap() takes three arguments:
– The indent string for the first line in a paragraph.
– The indent string for subsequence lines.
– The unformatted text to be wrapped.
– #!/usr/bin/perl – use warnings;
– use strict;
– use Text::Wrap;
–
– my $indent_first = “ “;
– my $indent_subsq = “”;
–
– my $text = "The bartender's smile widened. His ugliness was the stuff of legend. In an age of
affordable beauty, there was something heraldic about his lack of it. The antique arm whined as he reached for another mug.”;
– –
Example 1: Text::Wrap
• Output:
•
– The bartender's smile widened. His ugliness was the stuff of legend. In an age of affordable beauty, there was something heraldic about his
lack of it. The antique arm whined as he reached for another mug.
–
• Text::Wrap also has a variable called $columns, which determines how many columns the text wraps to (how many characters across the terminal). Unlike wrap(), $columns isn't exported from
Text::Wrap by default so you have to refer to it explicitly.
•
– #start of program just like before –
– $Text::Wrap::columns = 25;
–
– print wrap ($indent_first, $indent_subsq, $text);
Example 1: Text::Wrap
Example 1: Text::Wrap
• Output:
– The bartender's – smile widened. His
– ugliness was the stuff – of legend. In an age of – affordable beauty, there – was something heraldic – about his lack of it.
– The antique arm whined – as he reached for
– another mug.
Benefits of modules
• Benefit number 1: Modules save time and effort!
•
• Benefit number 2: Code has greater portability
•
• Benefit number 3: Modularity (no, really)
Saving time and effort
• There are thousands of Perl modules out there for you you use.
• These cover a huge range of common and not so common tasks.
• If a module has been written to do what you are intending to do, USE IT!
• Reinventing the wheel is pointless, unless you really can invent a better wheel.
• If you need to make a connection to a website, scrape the text contents, create a PDF from the resulting text and then index the PDF in a
PostgreSQL database then then someone else has done all the hard work for you already. Best of all they've put it on the internet and are prepared to share it with you.
Greater portability
• Perl modules are generally written with portability in mind. Again this lets someone complete the hard work of the task you want to do.
• What happens if you want to move a file from within your Perl program. Perl doesn't actually have a builtin “move” function.
• As you're stalwart Unix/GNU Linux types you will probably use system or exec to call /bin/mv.
• Or end up doing the least keystrokes solution:
•
• `mv oldfile.txt newfile.txt`;
•
•
Greater portability
• This works fine – as long as you're are on a UNIX or GNU/Linux operating system. But Perl runs on anything its been ported to,
including Windows and even Symbian. These other systems may not have a mv command – and then your code will fail!
• This however is portable across all operating systems:
•
– use File::Copy;
– move (“oldfile.txt”, “newfile.txt”);
Modularity
• As the name suggests, modules are modular.
• We have already touched on this point!
•
• With modules you can parcel up bits of code that do specific tasks (e.g.
wrapping text) into discrete bundles, which can be reused elsewhere.
•
• If the code needs to be updated you only need to change the module, not dozens of Perl programs. When you've been writing code for a while this will be very useful!
A note on objects
• From time to time you will run across modules that are “object
oriented” (OO).
•
• To learn more about this type of Perl programming we recommend “Perl Objects, References & Modules” (aka the Alpaca book).
•
• At this stage it is not necessary to know much about OO programming concepts, but it will be very useful to learn the syntax it uses so that you can incorporate OO Perl modules into your own code.
A brief word about objects
• Objects represent complex entities, such as people, books, protein or DNA sequences.
• In order to use an object you generally have to create one first.
• Syntactically this is quite simple:
– $bela = new Student();
•
• You can then interact with objects using methods, which work just like subroutines:
– print $bela->gradeAverage();
Example 2: Net::FTP
• Net::FTP is an objectoriented Perl module that allows you to access FTP servers on the internet from Perl. This might be useful if you
wanted to grab nightly Genbank updates automatically without having to log in by hand.
•
• As usual you start by importing the module:
– use Net::FTP;
• Then you create a new Net::FTP object:
– $ftp = new Net::FTP(“ftp.bio-linux.net”);
Example 2: Net::FTP
• Now you can interact with your new object in many new and exciting ways:
• Send the username and password (login):
– $ftp->login(“username”, “password”);
• Change to the directory where your file is:
– $ftp->cwd(“/pub/perl_course”);
• Retrieve the file you're interested in:
– $ftp->get(“intro_to_modules.pdf”);
• Terminate the connection when finished:
– $ftp->quit();
Modules to make Perl easier
• There are even modules to make Perl read
• English.pm (use English;) provides aliases for the builtin variables whose names no one seems to like to read. This means instead of
referring to $/ (the record separator) you can call it $RS or
$INPUT_RECORD_SEPARATOR to make your code immediately more readable.
• Diagnostics.pm (use Diagnostics;) produces much more verbose warning diagnostics about program errors.
• Basically it ties in perldiag (perldoc perldiag) (Perl diagnostic) error descriptions with the Perl compiler and interpretor errors, giving diagnostics that are far more explicative and human readable.
Module documentation
• When you install Perl modules documentation for the modules is also installed.
• To read the documentation supplied you can use the perldoc
command. The perldoc command will enable you to read Perlish information on just about every aspect of Perl you can think of (and some aspects you wouldn't think of!):
– perldoc File::Copy
• Alternatively on UNIX and GNU/Linux you can use the man command:
– man File::Copy
• On Windows HTML documentation is generally available when you install Perl.
Further reading
• For the “official” module documentation:
perldoc perlmod
• For a list of standard modules:
perldoc perlmodlib
• To read in the bath, in your lunchbreak, once you have finished
“Learning Perl”:
Learning Perl Objects, References and Modules by Randal L Schwartz with Tom Phoenix (O'Reilly) ISBN: 0-596-00478-8
Acknowledgments
• This talk has been adapted by that given at the EGTDC Perl Course 2003 by Simon Whitaker ([email protected]).
• Simon gave us full permission to modify and redistribute this talk. The 2004 talk was modified by Dan Swan ([email protected]).
• This work is licensed under the Creative Commons Attribution
NonCommercialShareAlike License. To view a copy of this license, visit http://creativecommons.org/licenses/byncsa/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California
94305, USA.
• The book quote in the Text::Wrap example comes from
“Neuromancer” a novel by William Gibson and is © William Gibson