2.3 Using do

The Skipper has placed a few common navigation subroutines into navigation.pl. If the Skipper merely inserts:

do "navigation.pl";
die $@ if $@;

into his typical navigation program, it's almost the same as if the eval code were executed earlier.[2]

[2] Except in regard to @INC, %INC, and missing file handling, which you'll see later.

That is, the do operator acts as if the code from navigation.pl were incorporated into the current program, although in its own scope block so that lexicals (my variables) and most directives (such as use strict) from the included file don't leak into the main program.

Now the Skipper can safely update and maintain only one copy of the common subroutines, without having to copy and recopy all the fixes and extensions into the many separate navigation programs he is creating and using. See Figure 2-1 for an illustration.

Figure 2-1. The navigation.pl file being used by the other navigation programs

Of course, this requires a bit of discipline because breaking the expected interface of a given subroutine will now break many programs instead of just one.[3] Careful thought will need to be given as to how to design and write reusable components and modular design. We'll presume The Skipper has had some experience at that.

[3] In later chapters, you'll see how to set up tests to be used while maintaining reused code.

Another advantage to placing some of the code into a separate file is that other programmers can reuse the Skipper's routines and vice versa. For example, suppose the Skipper's sidekick (we'll call him "Gilligan") writes a routine to drop_anchor( ) and places it in the file drop_anchor.pl.[4]

[4] The .pl here stands for "perl library," the common extension used for included Perl code. It is unfortunate that some non-Unix Perl vendors also use to use the same extension for the top-level Perl programs, because you then can't tell whether something is a program or a library. If you have a choice, the experts recommend ending your program filenames with .plx ("Perl executable"), or better yet, with no extension at all unless your system requires one.

Then, the Skipper can use the code with:

do "drop_anchor.pl";
die $@ if $@;
drop_anchor(  ) if at_dock(  ) or in_port(  );

Thus, the code is brought into separate files to permit easy maintenance and interprogrammer cooperation.

While the code brought in from a .pl file can have direct executable statements, it's much more common to simply define subroutines that can be called by the code containing the do.

Going back to that drop_anchor.pl library for a second, imagine what would happen if the Skipper wrote a program that needed to "drop anchor" as well as navigate:

do "drop_anchor.pl";
die $@ if $@;
do "navigate.pl";
die $@ if $@;
drop_anchor(  ) if at_dock(  );

That works fine and dandy. The subroutines defined in both libraries are available to this program.