(Banners provided as an OO Community Service to help promote OO Classics.
If you want to know more about OO, you can't do any better than these IMHO!)
From Paul S R Chisholm <psrc@exmachina.com> Organization Ex Machina Date Tue, 10 Dec 1996 15:40:38 -0500 Newsgroups comp.lang.perl.misc Message-ID <32ADCAC6.1B68@exmachina.com>
One of Perl 5's design goals is to make modules much easier to use than they are to build. Good news: You've probably used a lot of Perl 5 modules, and it was easy. Bad news: You've thought of making your own module, and it looks really complicated. Worse news: It *is* really complicated. Better news: Here are some hints on how to do it. There are various level of sophistication; I've picked some combinations of things you can do, and described them below. There's an *awful* lot on this subject I don't know. I hope others will help fill in the gaps. Level one: Make sure you have some useful, working Perl code. (Avoid false laziness.-) "Code isn't reusable until it's usable." Level two: Put some reusable Perl code into a separate ("module") file. This file should probably have a ".pm" suffix (or maybe a ".pl" suffix, especially if you want it to be compatible with Perl 4). All the names (of variables and subroutines) defined in the module file will be in the name space that's active when you use or require the file. To find the directory the file is in, pass the -I flag to the Perl interpreter, or put a "use lib" in the client code, or update @INC in a BEGIN block in the client code. Don't bother with a "shebang" (#!/usr/bin/perl) at the beginning of the module file; this is (like a) library, not an executable. The last executable statement should return true ("1;" is the usual idiom). Level three: Put a package statement at the beginning of the module file. The package name should be an identifier that starts with a capital letter, but isn't all capital letters. It should be the same as the base name (less the ".pl" or ".pm" suffix) of the module file. For example, you might have a package called Fizzbin; it would start with a "package Fizzbin;" statement, and would be stored in a file called "Fizzbin.pm". All the names defined in the module file will be in the Fizzbin name space; to invoke them the deal subroutine, you'd call &Fizzbin::deal(). Level four: Derive from Exporter, and start letting the user control which names from your module file end up in the global name space. Near the beginning of your module file, you'll need three lines: use Exporter; @ISA = qw(Exporter); @EXPORT = qw(...); where "..." is the list of names from the module that should be put in the global name space. (The qw() notation is a Perl 5 trick for getting a list of quoted words. qw(a b c) is the same as ('a', 'b', 'c'), including the lack of interpolation.) Start reading about the Exporter module, and re-read the description of the use statement. Knowing something about Perl 5's object oriented facilities will help. Level five: More control. Set @EXPORT_OK and maybe %EXPORT_TAGS and @EXPORT_FAIL. See the Exporter module documentation for details. Level six: Add Pod tags. (Why defer this until now? No good reason; do it earlier if you want.) The fine print says, any line in a place that could be a statement, but starts with an equals sign, is the beginning of a Plain Old Documentation section. Everything from that line, down to (and including) a line that begins "=cut", will be ignored by the Perl interpreter. Such lines will, however, be read by the various pod utilities: pod2text, pod2html, pod2man, pod2latex, etc. Pod isn't described in the Blue Camel book, but you probably have a perlpod man page (generated by pod2man). Level seven: Defer when your module's functions get loaded. Perl is an interpreter; it parses the Perl source every time. The more source it has to parse at start-up, the more time goes by between starting a Perl script and its first "real" activity. Thus, there are various ways to defer when code gets parsed. If you're lucky, some code may never get parsed. If you're unlucky, all of the code will get parsed anyway, and the overhead will increase your program's total execution time. Are you feeling lucky? (Note: CGI scripts won't appear to start any faster with these techniques. Well, maybe "non-parsed header" CGI scripts will.) There are three "common" ways (supported by pieces of the standard Perl distribution) to defer loading. (I don't really understand any of them; caveat reader.) The first way is to use AutoLoader (and the AutoSplit utilities). The idea is to break the module up, with each function definition in its own file. These files are parsed (just in time) the first time the function is called. The second is to use DynaLoader. This ... um, I don't know what this does. The idea (I think) is to pick up functions (written in C) from dynamically loaded (shared) libraries. The DynaLoader module description in the Blue Camel implies that a few lines do everything you need, except that a lot more needs to be done. I've seen the parts of the on-line documentation that describe all this; I just haven't read them (yet). The third (common) way is to use SelfLoader. This puts the class definitions into a string, which is evaluated (just in time) when the class is used (or something like that). There are more than three ways to do it. These three are just the ones supported by stuff in the Blue Camel. Level eight is to use ExtUtils::MakeMaker to build and install your module. The Blue Camel suggests that, if you just put in the files you need, the things that need to happen will happen. I'm not sure exactly what things those are. As promised, I left a lot out. Anyone want to pick up where I left off? --Paul S. R. Chisholm, AirMedia group, Ex Machina, Inc. mailto:psrc@exmachina.com http://www.exmachina.com/~psrc I'm not speaking for the company, I'm just speaking my mind
[ Eiffel in a Nutshell.. | Introducing Eiffel.. | Eiffel Compilers | Teaching Eiffel | Java implications for Eiffel | C Hackers | Bertrand Meyer Tribute | OOSC2 Update | OO SoapBox ]