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

Le
schirrms
Bonjour,

C'est mon premier post sur ce groupe, donc, rapide présentation :
Je ne suis pas développeur, mais en tant qu'administrateur de réseaux
et systèmes, j'ai déjà un certain nombre de scripts (en shell, awk,
bat et perl) qui tournent.
Ces deux dernières années, je n'ai quasi plus qu'écrit en perl, ce qu=
i
ne fait pas de moi une référence de ce language :-)
Je vous sollicite pour le point suivant :
j'ai écrit deux librairies 'orientées objet', une qui me sert à gér=
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 première 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 manière la plus 'lâche' possible. En d'autres
termes, je ne souhaites pas que dnscmd soit obligée de faire un appel
direct à logit, mais je voudrais au contraire que le programme
principal passe une référence à cette fonction à dnscmd.
Ainsi, vu de la librarie dnscmd, si la référence a été passée, le=
s
messages de débug sont passés à cette fonction, sinon dnscmd affiche
les messages de débug sur la sortie standard (ou stderr, là n'est pas
le problème).

Ouf ! quel long post !

1) Me 'fourvoi-je' complètement ? Ma démarche est-elle incohérente ?
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 don=
c,
depuis la librarie dnscmd, j'arrive à faire $$pouetpouet->log, mais ce
n'est pas vraiment 'indépendant comme processus !

Merci d'avance,
Pascal
Vidéos High-Tech et Jeu Vidéo
Téléchargements
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