Schrift
[thread]11028[/thread]

OOP, Parameter fuer Konstruktor pruefen

Tags: Ähnliche Threads

Leser: 2


<< >> 10 Einträge, 1 Seite
styx-cc
 2007-12-14 15:55
#103889 #103889
User since
2006-05-20
533 Artikel
BenutzerIn

user image
Hallo.
Ich wollte eigentlich nur fragen wie ihr die parameter, die eure Konstruktoren bekommen ueberprueft, da ich gerade wieder ein bisschen rumspiele:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sub new {
  ref (my $class = shift) && croak 'class name needed in constructor';
  my $self = {@_};
  $self->{$_} = $self->{$_} || '' for(qw/db user pass/);
  bless $self, $class;
  $self->connect();
  $self;
}

sub connect {
  my $self = shift;
  my $dbh = DBI->connect("dbi:mysql:$self->{'db'}", 
                                                $self->{'user'}, 
                                                $self->{'pass'})
                     || croak "DB-error: $DBI::errstr\n";
  $self->{'db_handle'} = $dbh;
}


In Zeile 4 guck ich halt ob ein Parameter gegeben wurde...
Gibt es da elegantere Methoden? Z.b. wie bei Perl-Tk wo angegeben wird welche Methoden erlaubt sind und welche Optionen er nicht kennt. Oder prueft man das in der Regel nicht, oder gibt man ein croak wenn Optionen vermisst werden?
Ich hab ein wenig gegoogelt und mir ein paar Tk-Widgets angeschaut, aber aufschlussreich war das irgendwie nicht.

MfG
Pörl.
renee
 2007-12-14 16:12
#103890 #103890
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Optionale Parameter sollte man vielleicht nicht überprüfen, bei anderen würde ich mit croak abbrechen wenn sie nicht gegeben sind (und man sie nicht anderweitig setzen kann).
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Struppi
 2007-12-14 18:19
#103893 #103893
User since
2006-02-17
628 Artikel
BenutzerIn
[Homepage]
user image
In dem Fall würde ich auch erst in der sub prüfen, wo du die Werte verwendest, es könnte ja sein das dein Programm die Werte noch per $obj->{user} nach new() setzt, dann ist auch die Schleife in Zeile 4 überflüssig (ist sie meiner Meinung sowieso, da es in dem Fall egal ist ob du undefinierte Werte oder ein Leerstring hast)
#Kein Kommentar
 2007-12-14 18:56
#103894 #103894
User since
2007-06-09
575 Artikel
HausmeisterIn
[default_avatar]
aber naja, $obj->{user} sollte von dem benutzer des moduls sowieso nicht
benutzt werden, da man nicht immer 100% weiß ob ein objekt ein hash- oder eine
array-referenz ist. außerdem ist doch die ->new () - methode dazu da, das objekt
mit seinen parameter zu erschaffen, es hat doch kein sinn danach noch parameter
mit der direkten art zu setzen. wenn man schon die OOP verwendet, sollte man
lieber immer über die dokumentierten methoden auf das objekt zugreifen.


du könntest doch alle parameter in ein hash speichern und ihnen einen wert geben,
ob sie dringend benötigt werden. irgendwie so:


Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
my %parameter = @_;

my %option = (
                '-db'   => 'required',
                '-user' => 'required',
                '-pass' => 'required',
                '-extra'        => 'optional',
        );

foreach my $parameter (keys %parameter){
        unless (exists $option{$parameter}){
                warn "Unknown parameter '$parameter'";
                next;
        }

        # und so weiter...
}
Gerade weil wir alle in einem Boot sitzen, sollten wir froh sein, dass nicht alle auf unserer Seite sind
Struppi
 2007-12-14 20:27
#103896 #103896
User since
2006-02-17
628 Artikel
BenutzerIn
[Homepage]
user image
#Kein Kommentar+2007-12-14 17:56:46--
aber naja, $obj->{user} sollte von dem benutzer des moduls sowieso nicht
benutzt werden, ...
Sollte, ja. Aber wer hindern den Benutzer daran?

Da die Parameter nur in einer Funktion benötigt werden, würde es sich auch anbieten diese dort zu übergeben, OO heißt ja nicht, dass die Methoden keine Parameter kriegen dürfen.
pktm
 2007-12-14 22:19
#103897 #103897
User since
2003-08-07
2921 Artikel
BenutzerIn
[Homepage]
user image
Struppi+2007-12-14 19:27:30--
#Kein Kommentar+2007-12-14 17:56:46--
aber naja, $obj->{user} sollte von dem benutzer des moduls sowieso nicht
benutzt werden, ...
Sollte, ja. Aber wer hindern den Benutzer daran?



So wirklich hindern kannst du den Benutzer nicht daran, außerd du verwendest die entsprechenden Techniken.
Aber das soll *dich* ja nicht daran hindern eine ordentliche Initialisierung zu forndern :)
http://www.intergastro-service.de (mein erstes CMS :) )
pq
 2007-12-15 00:07
#103906 #103906
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
der benutzer soll die dokumentierten methoden verwenden. wenn er das nicht tut,
ist er einfach mal selbst schuld =)
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Strat
 2007-12-16 13:41
#103927 #103927
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
Struppi+2007-12-15 13:03:54--
daher würde ich die Prüfung eben in den Aufruf von connect verpacken, sinnvollerweise z.b. über -param => 'value', dann läßt sich die Funktion leicht anpassen.


Ich bin eher dafuer, die Parameter im init ueberpruefen zu lassen. Man kann ja ein paar check-Methoden implementieren, die je nach verwendung die Parameter testen, und die aus dem init heraus aufgerufen werden. Den entsprechenden check sollte man zusaetzlich auch noch mal im connect ausfuehren. Und wenn man die DB aendert, braucht man nur die entsprechende check-Methode anpassen oder vielleicht erweitern, z.B.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
sub check_mysql_params {
    my( $self ) = @_;

    foreach my $attr ( qw( db username pass ) ) {
        unless( defined $self->$attr ) {
            croak( "Error: attribute '$attr' not set" );
        }
    }
    # eventuell hier noch den connect testen

    return $self;
} # check_mysql_params

sub init {
    my( $self, %params ) = @_;

    # parameter hier setzen
    
    my $driver = $self->driver || 'mysql';
    
    my $checkDriverParamsMethod = "check_${driver}_params";
    if( $self->can( $checkDriverParamsMethod ) {
        $self->$checkDriverParamsMethod;
    }
    else {
        croak "Error: no method '$checkDriverParamsMethod' existing";
    }

} # init

oder so aehnlich.

Wenn ein Script sehr lange laeuft (z.B. mehrere Stunden), dann ist es oft hilfreich, wenn alles so frueh wie moeglich ueberprueft werden kann.
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
Strat
 2007-12-15 12:49
#103936 #103936
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
Ich wuerde die Initialisierung in eine eigene sub namens init packen; dann hat der User die Wahl, ob er den Kram gleich beim new mitgeben will oder erst beim init. Dann würde ich object interface methoden schreiben, ueber die auf die einzelnen Attribute zugegriffen werden koennen (und das dann innerhalb der Klasse auch machen)
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
my @objectInterfaceMethods = qw( db user pass db_handle );

foreach my $method ( @objectInterfaceMethods ) {

    # anonyme sub erzeugen
    my $sub = sub {
        my( $self, @params ) = @_;

        $self->{ $method } = $params[0] if @params;

        return $self->{ $method };
    }; # sub

    # sub in der symboltabelle unter dem Namen $method verankern
    no strict 'refs';
    *{ $method } = $sub;

} # foreach

sub new {
    my( $class, @params ) = @_;

    croak 'class name needed in constructor' if ref $class;

    my $self = bless( {}, $class );

    $self->init( @params ) if scalar @params;

    return $self;
}

sub init {
    my( $self, %params ) = @_;

    foreach my $param ( keys %params ) {
        if( $self->can( $param ) ) {
            $self->$param( $params{$param} );
        }
        else {
            croak( "Invalid param '$param'" );
        }
    } # foreach

   # hier eventuell noch ueberpruefen, ob alle benoetigten parameter gesetzt sind
   # ...

  $self->connect();

  return $self;
}

sub connect {
    my $self = shift;
    my $dbh = DBI->connect("dbi:mysql:" . $self->db, 
                                                $self->user, 
                                                $self->pass)
                     or croak "DB-error: $DBI::errstr\n";
    $self->db_handle( $dbh );

    return $self;
}

dann hast du es einfacher, den Kern (hier hashRef) jederzeit auszutauschen


----
Modedit Gwendragon:
Quellcode repariert wg. inkorrektem Highlighting
----
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
Struppi
 2007-12-15 14:03
#103940 #103940
User since
2006-02-17
628 Artikel
BenutzerIn
[Homepage]
user image
pktm+2007-12-14 21:19:24--
So wirklich hindern kannst du den Benutzer nicht daran, außerd du verwendest die entsprechenden Techniken.
Aber das soll *dich* ja nicht daran hindern eine ordentliche Initialisierung zu forndern :)
Nichts.
Ich verwende für Zugriffsmethoden eine selbstentwickelte Abwandlung von
CPAN:Class::Accessor. Aber die "ordentliche" initialisierung sehe ich hier nicht. Einmal ist wie schon erwähnt das vorbelegen mit einem Leerstring nicht überflüssig, ausserdem sind es keine Werte die das Modul braucht, sondern lediglich eine Methode.

OO ist ja gerade für solche Fälle nicht unpraktisch, wenn man statt DBI oder statt mySQL etwas anderes benutzt, sind diese Angaben u.U. unnötig und andere Angaben nötig, daher würde ich die Prüfung eben in den Aufruf von connect verpacken, sinnvollerweise z.b. über -param => 'value', dann läßt sich die Funktion leicht anpassen.
<< >> 10 Einträge, 1 Seite



View all threads created 2007-12-14 15:55.