> Hi all I'm trying to write a basic class that will contain some 
> configuration details, unfortunately it bombs out and doesn't do anything.
> 
> ################### start of class ###########################
> #configuration.pm
> package configuration;
> use strict;
> 
> 
> sub new{
>     my $class=shift;
>     my $self=shift;


And what is getting shifted into $self?  You only call the constructor with one 
(implicit) parameter - the class-name

$configuration = configuration->new; 

is (nearly) equivalent to 

$configuration = configuration::new('configuration');




> 
>     bless($self, $class);
>     return $self;
> }

A better constructor might be (assuming you're going to represent your
object as a hash-reference, which is the most popular, but not only
way to do it.  (read and reread perltoot until you understand all of it).

sub new {
    my $class = shift;
    bless ({}, $class) ;
    return $self; 
}


> 
> sub get_conf{
>     my $self=shift;
>     my %conf=(
>               db_name="bla1",
>             username="bla2",
>             password="bla3"
> 
>     );

Well, the problems here are manifold:

1)  The syntax for generating a hash is 

    my %conf = ( db_name => 'bla1',
                 username => 'bla2',
                 password => 'bla3' ) ;


2) You create and return a hashref without making any change to the
   object;  Maybe what you meant to do was something more like:

sub get_conf { 
    my $self = shift;
    my %conf = ( db_name => 'bla1',
                 username => 'bla2',
                 password => 'bla3' ) ;

    foreach my $k ( keys %conf ) {
        $self->{$k} = $conf{$k};
    }

    return $self; 
}


> Mt CGI script is this:
> 
> ##################### CGI Script #######################
> #!/usr/bin/perl -w
> use strict;
> use configuration;
> 
> print "Content-type: text/html\n\n";
> 
> my $conf=configuration->new;
> my $conf->get_conf;


> 
> print "$conf->{'db_name'}";

This is a subtler but much more dreadful problem:

ISO8859-1 doesn't provide a bloody skull-and-crossbones character --
but this should be set in animated red flashing bell-ringing type.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! DO NOT DIRECTLY ACCESS THE UNDERLYING STRUCTURE OF YOUR OBJECTS !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

If you have to, print that out and paste it to your monitor.

Provide accessor and mutator functions (a/m) for the member data.

sub db_name {
    my $self = shift;
    if (@_) {
        $self->{db_name} = shift;
        return $self;
    } else {
        return $self->{db_name};
    }
}

This does lead to a philosophical discussion:  What should the mutator
return?

There are pretty much three values that make sense:

1)  the now new value of db_name
2)  $self
3)  The previous value of db_name

Number one is a tautology -- it is the least useful -- you KNOW what
you just set the value to, why bother returning it.

Number two is almost a tautology - but it allows you to use
constructions such as:

$self->db_name('dbi:pg:dbname=data')->username('webserver')->password('secret');

I use this in all of my base classes.

If I didn't return $self, I would choose number three -- as it is the
only of the three options that gives you some piece of data you didn't
pass INTO the function, and is sometimes useful.

rewriting my a/m function would look like:

sub db_name {
    my $self = shift;
    if (@_) {
        my $prev = $self->{db_name}; 
        $self->{db_name} = shift;
        return $prev; 
    } else {
        return $self->{db_name};
    }
}

This allows you to write code like:

my $old_db = $self->db_name('dbi:pg:dbname=tempdata');

$self->do_something(); # with the temporary database

$self->db_nmae($old_db); # go back to the original database


Now -- to get back to my first warning:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! DO NOT DIRECTLY ACCESS THE UNDERLYING STRUCTURE OF YOUR OBJECTS !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

"WHY!!?", I hear you cry.

Because today, you're just storing the db_name in the object.  But
next month, you need to make a change:

Boss:  Now we need to automatically change the underlying database
based on which customer number is stored in the object, because each
configuration comes out of a different database.

Now, we have two possible scenarios:

Stupid-self:  Oh, shit.  I hadn't thought of that.  I have to search
for EVERY place I *USED* the configuration object, and make a change.  

Smart-self: No problem.  I just change the semantics in
configuration.pm and every place that used the db_name method will
automatically Do The Right Thing.

sub db_name {
    my $self = shift;

    # I will pull the customer_number out so I can use 
    # it in a string interpolation

    my $customer_number = $self->customer_number;

    my $db_name = "dbi:pg:dbname=cust${customer_number}data";
    return $db_name;
}

So, in summary

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! DO NOT DIRECTLY ACCESS THE UNDERLYING STRUCTURE OF YOUR OBJECTS !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

The only place you should ever see something of the form 

$self->{foo}

is *INSIDE* the defining class.

And even there, you *USUALLY* should not.  Notice in my little
example, I used $self->customer_number.

Even though I was "inside" the class for configuration, and I "know"
that customer_number is an attribute of the object, it is Better to
avoid using my insider knowledge unless there is a Very Good Reason.

Places that include Very Good Reason is handling complex
polymorphism; writing generic a/m methods; questions of caching of
high-cost computations.

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        Lawrence Statton - [EMAIL PROTECTED] s/aba/c/g
Computer  software  consists of  only  two  components: ones  and
zeros, in roughly equal proportions.   All that is required is to
sort them into the correct order.



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to