[CLOS] Question sur les modules

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

[CLOS] Question sur les modules

Message par boddhi »

Salut à tou(tes),

Je me lance un peu tardivement dans la création de mon premier module et j'ai une question sur la portée des variables utilisées à l'intérieur de ce module.

En préambule, je vais expliquer pourquoi je souhaite me tourner, à tort où à raison, vers un module.
J'ai jusqu'à maintenant un code utilisé en Include par plusieurs sources.
Ces sources récupèrent quelques données à partir de ce fichier inclus qui, lui, stocke en variables globales un très grand nombre de données sous forme de listes et de maps, structurées ou non. Ces listes et maps doivent être stockées en Global pcq utilisées par plusieurs procédures dans le fichier inclus.

J'utilise donc une variable structurée globale que j'alimente en picorant, ici et là, des données dans ces listes et maps et que je récupère dans les sources appelants.
Le souci, c'est que toutes ces variables globales (ainsi que certaines structures) restent disponibles dans ces sources, ce dont je n'ai plus besoin puisqu'elles ne sont utiles que temporairement.

D'où mon idée du recours à un module.
En effet, dans la doc, il est indiqué dans l'exemple, que ce qui est déclaré dans DeclareModule est accessible à l'extérieur (donc global à l'ensemble du source) et que ce qui est déclaré à l'intérieur de Module est inaccessible à l'extérieur (donc local au module), hormis bien évidemment ce qui a été précédemment déclaré dans DeclareModule.

Je pensais donc trouver ici la réponse à mon objectif premier, à savoir que toutes mes déclarations globales dans le module resteraient locales dans ce module et ne serait plus accessibles une fois un UnuseModule appelé.
Mais, hélas, ce n'est pas le cas. Après tests sur mes sources et même de modules créés par d'autres, je constate que les variables déclarées en global dans le module restent en mémoire même une fois UnuseModule employé.

J'ai donc dû me méprendre sur le fonctionnement des portées à l'intérieur des modules (déclarées dans Module) et la fonction d'UnuseModule.

Ce dernier sert à quoi donc ? Il est indiqué qu'il retire les éléments du module, mais qu'est-il entendu par éléments ? Sert-il uniquement à éviter l'appel direct aux procédures, etc déclarées dans DeclareModule et obliger l'emploi de "NomDuModule::xxxxx()" ?

Y a-t-il un moyen de faire fonctionner un module comme une procédure, c'est-à-dire qu'une fois son utilisation terminée, il libère automatiquement les ressources qu'il a créées ou dois-je créer une autre procédure à l'intérieur qui les libèrera avec des FreeList, FreeMap, etc. ?

Merci pour vos réponses.
Dernière modification par boddhi le sam. 16/mars/2024 13:24, modifié 2 fois.
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Question sur les modules

Message par boddhi »

J'ai testé aussi avec des Define, en lieu et place des Global, avec des Shared dans les procédures locales du module mais même résultat : Les données listes et map restent dispos dans le source appelant...
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: Question sur les modules

Message par Mesa »

Il nous faut un peu de code exemple, 1 pour le module et 1 pour le source appelant.

M.
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Question sur les modules

Message par boddhi »

Salut Mesa,
Mesa a écrit : Il nous faut un peu de code exemple, 1 pour le module et 1 pour le source appelant.
Ici, un exemple très très simplifié de l'esprit de mon code originel.
Poster ce dernier en entier serait très long (il faudrait une 10aine de messages pour ce faire) et l'expurger aurait été bien plus éreintant :mrgreen:

Code : Tout sélectionner

EnableExplicit

DeclareModule TEST
  Structure STRUCTUREGLOBALE
    VariableG1.a
    VariableG2.s
    VariableG3.u[4]
    List VariableG4.l()
  EndStructure
  Global.STRUCTUREGLOBALE VariableG
  
  Declare Pc_ProcedureGlobale()
EndDeclareModule

Module TEST
  Structure STRUCTURELOCALE
    VariableL1.s
    VariableL2.a
    VariableL3.q[4]
    List VariableL4.l()
  EndStructure
  Global.STRUCTURELOCALE VariableL
  Global NewList Liste.s()
  
  AddElement(Liste()):Liste()="Element 1"
  AddElement(Liste()):Liste()="Element 2"
  
  Procedure Pc_ProcedureLocale()
    VariableL\VariableL1="Test"
  EndProcedure
  Procedure Pc_ProcedureGlobale()
    Pc_ProcedureLocale()
    VariableG\VariableG2=VariableL\VariableL1
  EndProcedure
EndModule
;
;
;
UseModule TEST
Debug "Valeur VariableG\VariableG2 avant : "+VariableG\VariableG2
Pc_ProcedureGlobale()
Debug "Valeur VariableG\VariableG2 après : "+VariableG\VariableG2
UnuseModule TEST
;
; Ici je m'attendais à ce que toutes les variables (variables structurées ou non, listes, etc) globales déclarées
; à l'intérieur du module disparaissent de la mémoire comme un peu ce qu'il se passe avec une procédure.
; Ce qui n'est pas le cas en explorant le visualisateur de variables.
ShowVariableViewer()
CallDebugger
;FirstElement(Liste()):Debug Liste()
Donc, comme écrit dans les commentaires, j'aurais pensé que les variables globales déclarées à l'intérieur du module disparaissaient une fois le module "déchargé" avec UnuseModule comme c'est le cas, par exemple, avec les procédures. Une fois sorti d'une procédure, toutes les variables déclarées à l'intérieur sont libérées de la mémoire.

Alors, en effet, les variables locales ne sont plus accessibles à l'extérieur. Un

Code : Tout sélectionner

FirstElement(Liste()):Debug Liste()
; ou un
Debug VariableL\VariableL1
génèrera une erreur mais néanmoins elle restent stockées en mémoire.

Mon souci, dans mon code, c'est que je stocke dans le module énormément de données par le biais de listes, maps, etc. dont je n'ai plus besoin une fois sorti du module.

J'ai dû me méprendre sur la fonction d'UnuseModule dont l'explication comportementale dans la doc est abusivement très très laconique :mrgreen:
J'ai donc fini par créer une procédure, à l'intérieur du module et déclarée dans DeclareModule, que j'appelle dans le source principal avant UnuseModule et qui libère (via des FreeXXXX()) toutes ces données,

Espérant avoir été clair dans mes explications. :wink:
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: Question sur les modules

Message par Mesa »

Les variables ne sont pas détruites donc elles restent accessibles au debugger, mais seulement lui, pas le reste du programme. Heureusement car ça permet de réutiliser un module même après un UnuseModule comme ci-dessous.

Tout fonctionne bien en fait.

M.


Code : Tout sélectionner

EnableExplicit

DeclareModule TEST
  Structure STRUCTUREGLOBALE
    VariableG1.a
    VariableG2.s
    VariableG3.u[4]
    List VariableG4.l()
  EndStructure
  Global.STRUCTUREGLOBALE VariableG
  
  Declare Pc_ProcedureGlobale()
  Declare.s Get()
  
EndDeclareModule

Module TEST
  Structure STRUCTURELOCALE
    VariableL1.s
    VariableL2.a
    VariableL3.q[4]
    List VariableL4.l()
  EndStructure
  Global.STRUCTURELOCALE VariableL
  Global NewList Liste.s()
  
  AddElement(Liste()):Liste()="Element 1"
  AddElement(Liste()):Liste()="Element 2"
  
  Procedure Pc_ProcedureLocale()
    VariableL\VariableL1="Test"
  EndProcedure
  
  Procedure Pc_ProcedureGlobale()
    Pc_ProcedureLocale()
    VariableG\VariableG2=VariableL\VariableL1
  EndProcedure
  
  Procedure.s Get()
  	ProcedureReturn VariableG\VariableG2
  EndProcedure
  
EndModule
;
;
;
UseModule TEST
Debug "Valeur VariableG\VariableG2 avant : "+VariableG\VariableG2
Pc_ProcedureGlobale()
Debug "Valeur VariableG\VariableG2 après : "+VariableG\VariableG2
UnuseModule TEST
;
; Ici je m'attendais à ce que toutes les variables (variables structurées ou non, listes, etc) globales déclarées
; à l'intérieur du module disparaissent de la mémoire comme un peu ce qu'il se passe avec une procédure.
; Ce qui n'est pas le cas en explorant le visualisateur de variables.


;=======================>>>>> VariableG n'est pas visible
Debug "Valeur VariableG\VariableG2 après : "+VariableG\VariableG2

; Debug TEST::Get(); accessible avec un getter, dans le module exclusivement.

; ShowVariableViewer()
; CallDebugger
;FirstElement(Liste()):Debug Liste()
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Question sur les modules

Message par boddhi »

Salut Mesa,
Mesa a écrit : Les variables ne sont pas détruites donc elles restent accessibles au debugger, mais seulement lui, pas le reste du programme.
Merci pour ta réponse.

Et, entre-temps, j'ai fait quelques tests qui m'ont amené à confirmer la persistance des valeurs de variables déclarées à l'intérieur du module, globales ou non (pour ces dernières, bien-sûr, seulement si elles sont déclarées à la racine du module c-à-d hors procédures)

Code : Tout sélectionner

EnableExplicit

DeclareModule TEST
  Structure STRUCTUREGLOBALE
    VariableG1.a
    VariableG2.s
    VariableG3.u[4]
    List VariableG4.l()
  EndStructure
  Global.STRUCTUREGLOBALE VariableG
  
  Declare Pc_ProcedureGlobale()
  Declare.s Get()
  
EndDeclareModule

Module TEST
  Structure STRUCTURELOCALE
    VariableL1.s
    VariableL2.a
    VariableL3.q[4]
    List VariableL4.l()
  EndStructure
  Global.STRUCTURELOCALE VariableL
  Global NewList Liste.s()
  
  Define.s VariableTexte
  AddElement(Liste()):Liste()="Element 1"
  AddElement(Liste()):Liste()="Element 2"
  
  Procedure Pc_ProcedureLocale()
    Shared.s VariableTexte
    VariableTexte="Essai"
    VariableL\VariableL1="Test"
  EndProcedure
  
  Procedure Pc_ProcedureGlobale()
    Protected.s VariableProcedure
    
    Shared.s VariableTexte
    Debug "Valeurs variables avant assignation : "
    Debug "  VariableProcedure : "+VariableProcedure
    Debug "  VariableTexte : "+VariableTexte
    Debug "  VariableL\VariableL1 : "+VariableL\VariableL1
    VariableProcedure="Valeur non persistante"
    Pc_ProcedureLocale()
    VariableG\VariableG2=VariableL\VariableL1
  EndProcedure
  
  Procedure.s Get()
  	ProcedureReturn VariableG\VariableG2
  EndProcedure
  
EndModule
;
;
;
UseModule TEST
Debug "Valeur VariableG\VariableG2 avant procédure module : "+VariableG\VariableG2
Pc_ProcedureGlobale()
Debug "Valeur VariableG\VariableG2 après procédure module : "+VariableG\VariableG2
UnuseModule TEST
;
; Ici je m'attendais à ce que toutes les variables (variables structurées ou non, listes, etc) globales déclarées
; à l'intérieur du module disparaissent de la mémoire comme un peu ce qu'il se passe avec une procédure.
; Ce qui n'est pas le cas en explorant le visualisateur de variables.
;=======================>>>>> VariableG n'est pas visible
;Debug "Valeur VariableG\VariableG2 après : "+VariableG\VariableG2
Debug "UnuseModule"
Debug "---------------------------------------"
UseModule TEST
Debug "UseModule"
Debug "Valeur VariableG\VariableG2 avant réinitialsation : "+VariableG\VariableG2
VariableG\VariableG2=""
Debug "Valeur VariableG\VariableG2 après réinitialsation et avant procédure module : "+VariableG\VariableG2
Pc_ProcedureGlobale()
Debug "Valeur VariableG\VariableG2 après procédure module : "+VariableG\VariableG2
 
Et en conséquence, je confirme également la conclusion que j'avais soupçonnée qui était que si je veux décharger la mémoire de tous tableaux, listes, maps, variables, etc. après utilisation du module, je dois, selon le type, les réinitialiser ou les "libérer"...

Cet aspect-là a au moins mérite d'être clair maintenant ! :) :wink:
 
Répondre