Probleme d'appel de fonctions dans des modules 'Objets'

Le
schirrms
Bonjour,

C'est mon premier post sur ce groupe, donc, rapide prsentation :
Je ne suis pas dveloppeur, mais en tant qu'administrateur de rseaux
et systmes, j'ai dj un certain nombre de scripts (en shell, awk,
bat et perl) qui tournent.
Ces deux dernires annes, je n'ai quasi plus qu'crit en perl, ce qu=
i
ne fait pas de moi une rfrence de ce language :-)
Je vous sollicite pour le point suivant :
j'ai crit deux librairies 'orientes objet', une qui me sert gr=
er
mes logs, une autre qui me fournit des fonctions de gestion d'un
serveur DNS. Ces deux librairies semblent fonctionner comme je le
souhaite.
J'initie la premire en faisant un
my $logit = MiscPS!!Log_It->new( parametres de log en fonctions de mes
besoins)
et la seconde en faisant
my $DnsCmd=Win32::dnscmd->new(parametres de connexion au serveur DNS,
et autres en fonctions de mes besoins).
Jusque l, tout va bien.
Dans mon programme principal, je fais parfois appel une fonction de
log en fonction du niveau de debug que j'ai mis en place. Cette
fonction est dans la librarie LogIT, je l'appelle ainsi :
$logit->debuglog(5, "$ph-$annu{ $ph }" );

Je souhaiterais permettre ma libraire dnscmd d'utiliser la fonction
debuglog, mais de la manire la plus 'lche' possible. En d'autres
termes, je ne souhaites pas que dnscmd soit oblige de faire un appel
direct logit, mais je voudrais au contraire que le programme
principal passe une rfrence cette fonction dnscmd.
Ainsi, vu de la librarie dnscmd, si la rfrence a t passe, le=
s
messages de dbug sont passs cette fonction, sinon dnscmd affiche
les messages de dbug sur la sortie standard (ou stderr, l n'est pas
le problme).

Ouf ! quel long post !

1) Me 'fourvoi-je' compltement ? Ma dmarche est-elle incohrente ?
2) Si je ne suis pas dans le gaz, comment passer une rfrence ? Je
suis arriv passer une rfrence la variable '$logit', et don=
c,
depuis la librarie dnscmd, j'arrive faire $$pouetpouet->log, mais ce
n'est pas vraiment 'indpendant comme processus !

Merci d'avance,
Pascal
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Paul Gaborit
Le #16762701
À (at) Tue, 9 Sep 2008 00:59:18 -0700 (PDT),
schirrms
1) Me 'fourvoi-je' complètement ? Ma démarche est-elle incohérente ?



Oui et non... Ça dépend du point de vue.

2) Si je ne suis pas dans le gaz, comment passer une référence ? Je
suis arrivé à passer une référence à la variable '$logit', et donc,
depuis la librarie dnscmd, j'arrive à faire $$pouetpouet->log, mais ce
n'est pas vraiment 'indépendant comme processus !



Il y a plusieurs moyens de répondre à votre besoin. En voici au moins
trois.

1- Une manière objet : celle que vous avez adoptée (ou presque). On
passe un objet en supposant qu'il a une méthode 'log'. On peut
"améliorer" la chose en passant en plus le nom de la méthode à
appeller ('log' peut-être remplacé par le nom d'une variable). Au
passage, pourquoi passer une référence à $logit : c'est un objet et
donc c'est déjà une référence !

2- Deuxième manière objet : définir une classe implémentant
l'interface de log attendue par les objets de la classe DNS. Définir
une instance par défaut qui fait un 'log' sur stderr par exemple. Et
enrober $logit dans une autre instance de cette classe pour qu'il
puisse remplacer l'instance par défaut.

3- Une manière par fermeture (closure) : définir une fermeture qui
cache l'objet $logit et l'appel à 'log' et passer cette subroutine
anonyme comme callback à dnscmd :

$dnscmd->install_callback_log(
sub {
# on peut ajouter des paramètres fixes (ici 5)
$logit->log(5, @_);
}
);

(la méthode 'install_callback_log' stocke la sub anonyme dans un des
attributs de l'objet $dnscmd. Posons que cet attribut s'appelle
'cblog'.)

Ensuite pour l'utiliser :

my $mes = "un message";
if (defined $dnscmd->cblog) {
$dnscmd->cblog->($mes);
} else {
print STDERR "$mesn";
}



--
Paul Gaborit - Perl en français -
schirrms
Le #16772601
On 9 sep, 11:35, Paul Gaborit Merci, merci beaucoup pour ces réponses ! Il m'a fallu un peu de temps
pour pouvoir les exploiter!
Il y a plusieurs moyens de répondre à votre besoin. En voici au moins
trois.

1- Une manière objet : celle que vous avez adoptée (ou presque). On
passe un objet en supposant qu'il a une méthode 'log'. On peut
"améliorer" la chose en passant en plus le nom de la méthode à
appeller ('log' peut-être remplacé par le nom d'une variable). Au
passage, pourquoi passer une référence à $logit : c'est un objet et
donc c'est déjà une référence !



C'est en fait ce que je cherchais à faire. Vous m'avez donné les clef
qui me manquaient, et maintenant çà fonctionne.
Simplement, je restais bloqué sur un point que je n'avais pas
détecté :
En fait, dans la fonction new de mon dnscmd j'avais mis :
$self->{logobject} = $_[0];
$self->{logfunct} = $_[1];

Et dans ma fonction _debug, j'avais mis ceci :
$self->{logobject}->$self->{logfunct}(4, "Bonjour de test2b-
tolog");



Ceci ne fonctionne pas, car je ne dois pas savoir comment 'protéger la
'variable' $self->{logfunct}.
Ce qui fonctionne, c'est ceci :
my $funct = $self->{logfunct};
$self->{logobject}->$funct(4, "Bonjour de test2b->tolog");

Je suppose qu'il existe une version plus élégante :-)


2- Deuxième manière objet : définir une classe implémentant
l'interface de log attendue par les objets de la classe DNS. Définir
une instance par défaut qui fait un 'log' sur stderr par exemple. Et
enrober $logit dans une autre instance de cette classe pour qu'il
puisse remplacer l'instance par défaut.



Là, j'avoue que çà dépasse mes compétences de compréhension. Si vous
avez quelques minutes à perdre pour détailler, ce sera pour ma culture
générale, sinon, ce n'est pas important.

3- Une manière par fermeture (closure) : définir une fermeture qui
cache l'objet $logit et l'appel à 'log' et passer cette subroutine
anonyme comme callback à dnscmd :

    $dnscmd->install_callback_log(
       sub {
          # on peut ajouter des paramètres fixes (ici 5)
         $logit->log(5, @_);
       }
    );

(la méthode 'install_callback_log' stocke la sub anonyme dans un des
attributs de l'objet $dnscmd. Posons que cet attribut s'appelle
'cblog'.)

Ensuite pour l'utiliser :

    my $mes = "un message";
    if (defined $dnscmd->cblog) {
       $dnscmd->cblog->($mes);
    } else {
       print STDERR "$mesn";
    }  




Ce mode là, je ne l'avais pas du tout imaginé, mais je l'ai testé, il
fonctionne parfaitement, magnifique (je reste un grand enfant face à
Perl :-)

Je vous remercie encore !

Pascal
Publicité
Poster une réponse
Anonyme