Re: Programming style: using Classes or inline

On Mar 16, 2006, at 2:30 PM, David wrote:

On Thu, Mar 16, 2006 at 09:52:20PM +1300, Grant McLean wrote:
On Wed, 2006-03-15 at 21:13 -0600, David wrote:

[...] "use strict" and separate files.

No, that's right, before you added 'use strict' all your variables were
global variables.  When you declared the variables with 'my', you
restricted their scope to the block they appeared in (eg: a subroutine)
or to the file if they weren't in a block.

What came as a surprise to me was that I couldn't have global variables. Again, I'm quite new to Perl and some of the rules are a bit unexpected.

"strict" doesn't prevent you from having globals. What it does is require that you use either fully-qualified package names or lexically-scoped variables.

Without "strict", any variable name is legal, and the scope is global by default. This was and is very handy for command-line one-liners and other quick hacks, but in Real Code is Very Dangerous. The most common case is that you can misspell a variable name and never know it until you've spent far too long tracking down the resulting logic bug.

So, "strict" essentially makes you declare your variables. With "my" you create a variable which is visible only within the containing lexical scope (the file, package, or block). With "our" you declare a variable that lives in this file but is visible to anyone who knows the package name. You can also say "use vars qw($foo @bar)" to achieve the same effect as "our $foo; our @bar;". To refer to these variables from other packages you must either refer to them with fully-qualified package names (e.g. $OtherPackage::foo) or set up the host package as an Exporter and import them into other packages.

All of this is documented in perl's online manual.

And, actually, i hesitate to mention all of this because globals really are not good things to use. They limit the ability of your packages to scale to multiple instances and tend to cause spaghetti- like interdependencies.

Avoid globals.

Learn to create classes. Perl makes it very easy. Once you understand classes, there's a slight change in initialization style to start creating subclasses of Glib::Objects so that you can create your own widgets. Here's a write-up that contrasts normal perl classes and Glib::Object-style classes.

if I were to adapt some of the routines to Classes, what's
normally best - separate files or a single file?

You can do either.  It's perfectly reasonable to declare multiple
classes in a single file.

With the above question, I meant keeping the classes in the same file as the mainline code. I know that in your tutorial, you stated that while developing your project, you kept separate files for the classes and the
mailine code, but that sometimes it was advantageous, especially after
development was complete, to merge them all into one file.

Whether to use one file or a bunch of files really depends on how the code will be used. When i have something that i want to deploy easily, i like to have all the classes in a single file so that the application consists of just one file. If i'm reusing code, i'll create installable modules.

An important thing to remember when placing a bunch of classes in one file is that execution order still matters. When using "require" or "use", your whole pm file will be parsed and then executed. If you have all the classes in one file, all of the code will be parsed, but whether it will be executed depends on the position in the file. To wit:

#!/usr/bin/perl -w
package ThingOne;
print "initializing ".__PACKAGE__."\n";
our $stuff = 42;
sub new { return bless { stuff => $stuff }, $_[0]; }

package main;
# here is some driver code.
use strict;
foreach my $class (qw(ThingOne ThingTwo ThingThree)) {
        my $thing = new $class;
        print "$thing\->{stuff} = $thing->{stuff}\n";

package ThingTwo;
print "initializing ".__PACKAGE__."\n";
our $stuff = 42;
sub new { return bless { stuff => $stuff }, $_[0]; }

package ThingThree;
print "running in ".__PACKAGE__."\n";
our $stuff;
        print "initializing ".__PACKAGE__."\n";
        $stuff = 42;
sub new { return bless { stuff => $stuff }, $_[0]; }


This prints out the following:

$ perl
initializing ThingThree
initializing ThingOne
ThingOne=HASH(0x9339d20)->{stuff} = 42
Use of uninitialized value in concatenation (.) or string at single- line 12.
ThingTwo=HASH(0x9339d98)->{stuff} =
ThingThree=HASH(0x9357080)->{stuff} = 42
initializing ThingTwo
running in ThingThree

Figuring out why is left as an exercise for you.  :-)

So, you then get to decide whether you want your main driver logic at the top or at the bottom of the file.

The web site is a good place for questions and quick
feedback too.

Yes, that would be a more apropriate place.  I do realize that this
question _was_ a bit OT for this list.

If everything was on-topic life would be quite boring. But i do try to spare y'all the tales of what crazy things my kids have done each day. =)

"that's it! you're a genius!" "yes. that's what i think. do you think i deserve a raise?"
    - dialogue from 'Godzilla versus Mothra', 1964

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]