Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

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

2 réponses
Avatar
schirrms
Bonjour,

C'est mon premier post sur ce groupe, donc, rapide pr=E9sentation :
Je ne suis pas d=E9veloppeur, mais en tant qu'administrateur de r=E9seaux
et syst=E8mes, j'ai d=E9j=E0 un certain nombre de scripts (en shell, awk,
bat et perl) qui tournent.
Ces deux derni=E8res ann=E9es, je n'ai quasi plus qu'=E9crit en perl, ce qu=
i
ne fait pas de moi une r=E9f=E9rence de ce language :-)
Je vous sollicite pour le point suivant :
j'ai =E9crit deux librairies 'orient=E9es objet', une qui me sert =E0 g=E9r=
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=E8re en faisant un
my $logit =3D MiscPS!!Log_It->new( parametres de log en fonctions de mes
besoins)
et la seconde en faisant
my $DnsCmd=3DWin32::dnscmd->new(parametres de connexion au serveur DNS,
et autres en fonctions de mes besoins).
Jusque l=E0, tout va bien.
Dans mon programme principal, je fais parfois appel =E0 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 }\n" );

Je souhaiterais permettre =E0 ma libraire dnscmd d'utiliser la fonction
debuglog, mais de la mani=E8re la plus 'l=E2che' possible. En d'autres
termes, je ne souhaites pas que dnscmd soit oblig=E9e de faire un appel
direct =E0 logit, mais je voudrais au contraire que le programme
principal passe une r=E9f=E9rence =E0 cette fonction =E0 dnscmd.
Ainsi, vu de la librarie dnscmd, si la r=E9f=E9rence a =E9t=E9 pass=E9e, le=
s
messages de d=E9bug sont pass=E9s =E0 cette fonction, sinon dnscmd affiche
les messages de d=E9bug sur la sortie standard (ou stderr, l=E0 n'est pas
le probl=E8me).

Ouf ! quel long post !

1) Me 'fourvoi-je' compl=E8tement ? Ma d=E9marche est-elle incoh=E9rente ?
2) Si je ne suis pas dans le gaz, comment passer une r=E9f=E9rence ? Je
suis arriv=E9 =E0 passer une r=E9f=E9rence =E0 la variable '$logit', et don=
c,
depuis la librarie dnscmd, j'arrive =E0 faire $$pouetpouet->log, mais ce
n'est pas vraiment 'ind=E9pendant comme processus !

Merci d'avance,
Pascal

2 réponses

Avatar
Paul Gaborit
À (at) Tue, 9 Sep 2008 00:59:18 -0700 (PDT),
schirrms écrivait (wrote):
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 - <http://perso.enstimac.fr/~gaborit/&gt;
Perl en français - <http://perl.enstimac.fr/&gt;
Avatar
schirrms
On 9 sep, 11:35, Paul Gaborit wrote:
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