OVH Cloud OVH Cloud

Pas de globales en win32

25 réponses
Avatar
Stephane Legras-Decussy
bonjour,

Me débrouillant maintenant pas mal en api win32, je souhaite passer
maintenant à des appli un peu serieuses. Comme il se doit, je veux bannir
de mon code les variables globales qu'on trouve toujours dans les exemples
win32.

mon problème est : où et comment déclarer les variables
qui seraient normalement dans le main() d'un prog console?

Je pense à les déclarer en static au début de la win proc comme
à l'air de la faire Petzold.

Est-ce bien la bonne méthode ?

--

10 réponses

1 2 3
Avatar
AMcD®
Stephane Legras-Decussy wrote:
bonjour,

Me débrouillant maintenant pas mal en api win32, je souhaite passer
maintenant à des appli un peu serieuses. Comme il se doit, je veux
bannir de mon code les variables globales qu'on trouve toujours dans
les exemples win32.



Il n'y a bien que dans les livres et les cours de facs qu'ont peu débiter
des trucs pareils. Évidemment, les variables globales sont à éviter au
possible, mais tout de même, de la à les proscrire !

mon problème est : où et comment déclarer les variables
qui seraient normalement dans le main() d'un prog console?



Il te faut déclarer tes variables... où elles doivent l'être ! C'est lors de
la conception, de l'étude de ton projet que tu vas définir l'étendue, le
type, la catégorie de tes variables. Un programme professionnel, ce n'est
pas, bon, je commence par virer tout ce qui est global... Il te faut
réfléchir à ce que tu cherches à faire. Ensuite tu décideras du type.

Je pense à les déclarer en static au début de la win proc comme
à l'air de la faire Petzold.

Est-ce bien la bonne méthode ?



Ben le static, c'est une forme de global...

--
AMcD®

http://arnold.mcdonald.free.fr/
Avatar
Stephane Legras-Decussy
AMcD® a écrit dans le message :
423cb603$0$21830$
Il n'y a bien que dans les livres et les cours de facs qu'ont peu débiter
des trucs pareils. Évidemment, les variables globales sont à éviter au
possible, mais tout de même, de la à les proscrire !



hum... pas de polémique :-)


Il te faut déclarer tes variables... où elles doivent l'être ! C'est lors


de
la conception, de l'étude de ton projet que tu vas définir l'étendue, le
type, la catégorie de tes variables. Un programme professionnel, ce n'est
pas, bon, je commence par virer tout ce qui est global... Il te faut
réfléchir à ce que tu cherches à faire. Ensuite tu décideras du type.



justement, je concois mon projet en blocs fonctionnels entrées -> sorties
...

il n'est pas question qu'une fonction lise ou modifie une donnée
non passée en parametre...
( pour des tas de raisons: maintenance, test unitaires, réutilisabilité,
etc)

donc pour des variables de durée de vie = toute la vie du programme,
je me demande comment faire.

sachant qu'une variable déclarée dans winmain aura une durée vie correcte
mais ne pourra pas être passée à la win proc (puisque ces parametres sont
fixés).

il ne reste donc que la possibilité de déclarer dans la win proc, mais
sachant
que la win proc est appellée de nombreuse fois, il faut forcement forcer en
static
pour conserver les valeurs.


exemple : j'ai un grand tableau de char appelé tab qui contient une image...
le but de mon appli est de faire divers traitement sur ce tableau...

où déclares-tu char *tab ?

si char *tab est global, c'est foutu si un jour je veux traiter 2 ou 3
images
dans mon appli...

si tab est passé en paramètre à chaque fonction, c'est enfantin de traiter
x images...
Avatar
AMcD®
Stephane Legras-Decussy wrote:
AMcD® a écrit dans le message :
423cb603$0$21830$
Il n'y a bien que dans les livres et les cours de facs qu'ont peu
débiter des trucs pareils. Évidemment, les variables globales sont à
éviter au possible, mais tout de même, de la à les proscrire !



hum... pas de polémique :-)


Il te faut déclarer tes variables... où elles doivent l'être ! C'est
lors de la conception, de l'étude de ton projet que tu vas définir
l'étendue, le type, la catégorie de tes variables. Un programme
professionnel, ce n'est pas, bon, je commence par virer tout ce qui
est global... Il te faut réfléchir à ce que tu cherches à faire.
Ensuite tu décideras du type.



justement, je concois mon projet en blocs fonctionnels entrées ->
sorties ...

il n'est pas question qu'une fonction lise ou modifie une donnée
non passée en parametre...
( pour des tas de raisons: maintenance, test unitaires,
réutilisabilité, etc)

donc pour des variables de durée de vie = toute la vie du programme,
je me demande comment faire.

sachant qu'une variable déclarée dans winmain aura une durée vie
correcte mais ne pourra pas être passée à la win proc (puisque ces
parametres sont fixés).

il ne reste donc que la possibilité de déclarer dans la win proc, mais
sachant
que la win proc est appellée de nombreuse fois, il faut forcement
forcer en static
pour conserver les valeurs.


exemple : j'ai un grand tableau de char appelé tab qui contient une
image... le but de mon appli est de faire divers traitement sur ce
tableau...

où déclares-tu char *tab ?

si char *tab est global, c'est foutu si un jour je veux traiter 2 ou 3
images
dans mon appli...

si tab est passé en paramètre à chaque fonction, c'est enfantin de
traiter x images...



Ben tu fais une variable globale (houla !) qui contient une structure simple

pointeur vers ton tab
pointeur vers la structure suivante

Ensuite tu ajoute, enlève des tab à volonté dans ta... liste chaînée que ça
s'appelle.

Sinon, j'ai du mal à te suivre. Ton programme comporte une winproc. Celle-ci
va gérer ton appel de traitement de tab suite à un appui sur un bouton, etc.
C'est dans la fonctiona ppelée alors que tu vas mettre en palce la structure
adéquate et la passer (pointeur) à la fonction de traitement...

Enfint, tu peux passer des paramètres à une Winproc, via lparam ou wparam,
des messages utilisateurs, etc.

As-tu bien lu le Petzold :) ?

--
AMcD®

http://arnold.mcdonald.free.fr/
Avatar
Vincent Burel
"Stephane Legras-Decussy" wrote in message
news:423cbd55$0$29112$


donc pour des variables de durée de vie = toute la vie du programme,
je me demande comment faire.




Pour les applicatifs un peu conséquents on se fait une unité qui va
s'occuper des variables globales. Cette unité va stocker ces données et
présenter un jeu de fonction à l'ensemble du programme pour utiliser ces
globales . C'est usuellement la méthodologie employé pour gérer les
ressources commune à l'application, Hinstance , répertoire de travail, icon,
font, couleur, brush etc... éventuellement des paramètres globaux.

Maintenant, il faut considérer le cas des des unité indépendantes, des unité
"c" qui existe déjà, et qu'on ré-utilise dans divers applications que l'on
programme, donc ne dépendant pas d'une unité commune, dans ce cas on prévois
une fonction de l'unité, généralement la fonction d'initialization, de
passer les globales qui lui seront utiles : typiquement le HINSTANCE de
l'application , voire des resources... etc...

Donc on a le choix suivant les cas, ou l'on se fait un centralisateur de
globale, ou l'on communique les globales aux unités qui en ont besoin. Mais
c'est vrai qu'on utilise plus du tout de variable globale , au sens de
variable visible par toute les unités de l'applicatif. par contre on utilise
des globale à l'unité , visible uniquement dans le fichier source qui les
déclare (déclaré en "c" avec le mot clef "static"). Ceci permet d'éviter des
probleme de conflit quand on assemble des unités différentes pour faire une
application.

De manière générale il faut voir une application comme une entreprise où
l'on mets en place divers services (divers composants logiciels) avec des
attributions particulières. Il suffit de garder à l'esprit deux questions :
"qui fait quoi ? " et "qui a cette compétence ?" ou "qui se doit d'avoir
cette compétence" pour avoir une organization qui se tient, donc au final un
logiciel qui se tient. La gestion des données (qu'elles soient globales ou
non) coulera de source...

VB
Avatar
Stephane Legras-Decussy
AMcD® a écrit dans le message :
423cc85b$0$21820$

Ensuite tu ajoute, enlève des tab à volonté dans ta... liste chaînée que


ça
s'appelle.



hum... ça me parait bien compliqué une liste chainée pour faire ça...


Enfint, tu peux passer des paramètres à une Winproc, via lparam ou wparam,
des messages utilisateurs, etc.



ok, j'ai jamais fais ça encore...


As-tu bien lu le Petzold :) ?



ben, pas tout... :-)

Merçi pour ta réponse.
Avatar
Stephane Legras-Decussy
Vincent Burel a écrit dans le message :
423d3436$0$11683$
[snip]

merçi pour cette longue et claire réponse qui répond parfaitement
à mes attentes !
Avatar
Alexandre
> hum... ça me parait bien compliqué une liste chainée pour faire ça...



peut-être mais ça te garantit que tu n'as pas obligatoirement UNE image mais
entre 0 et plusieurs...
Tu n'as pas précisé ton langage, si c'est C++ alors une solution pour les
variables globales c'est de les mettre dans un espace de noms (pour éviter
des collisions de noms) ou dans une classe, en statique (ce qui revient au
même).
Toujours avec C++, pour une liste chaînée, tu n'as qu'à utiliser std::list
Et encore avec C++, pour une chaine ça serait + simple avec std::string
qu'avec char*

Oublies les dernières lignes si tu programmes en C. Ce qui est peut-être le
cas vu que tu ne parles jamais d'objets...



Enfint, tu peux passer des paramètres à une Winproc, via lparam ou
wparam,
des messages utilisateurs, etc.



ok, j'ai jamais fais ça encore...


As-tu bien lu le Petzold :) ?



ben, pas tout... :-)

Merçi pour ta réponse.







Avatar
Vincent Burel
"Alexandre" wrote in message
news:423dd726$0$14221$
> hum... ça me parait bien compliqué une liste chainée pour faire ça...

peut-être mais ça te garantit que tu n'as pas obligatoirement UNE image


mais
entre 0 et plusieurs...
Tu n'as pas précisé ton langage, si c'est C++ alors une solution pour les
variables globales c'est de les mettre dans un espace de noms (pour éviter
des collisions de noms) ou dans une classe, en statique (ce qui revient au
même).
Toujours avec C++, pour une liste chaînée, tu n'as qu'à utiliser std::list
Et encore avec C++, pour une chaine ça serait + simple avec std::string
qu'avec char*

Oublies les dernières lignes si tu programmes en C. Ce qui est peut-être


le
cas vu que tu ne parles jamais d'objets...



hum, hum,

La mise en place d'une liste chainée se justifie si les block de données que
l'on veut gérer sont de taille variable ET si ces blocs représentent une
quantité non négligeable de mémoire (Aujourd'hui, plusieurs Mo) . Dans le
cas contraire la liste chainée ne se justifie pas et constitue même un signe
évident d'une mauvaise maitrise des techniques informatiques et de leur
déploiment dans une application...

VB
Avatar
Patrick Philippot
Stephane Legras-Decussy wrote:
mon problème est : où et comment déclarer les variables
qui seraient normalement dans le main() d'un prog console?



Bonjour,

Pour les données associées/associables à une fenêtre ou une classe de
fenêtre et qui doivent pouvoir être récupérées à tout moment,
j'ajouterai aux réponses précédentes la possibilité de stocker avec
chaque structure de fenêtre ou chaque structure de classe des données
privées que vous pouvez gérer avec SetWindowLong et GetWindowLong à
l'offset GWL_USERDATA. Il faut simplement penser à réserver l'espace
nécessaire dans les champs cbClsExtra et cbWndExtra au moment de la
déclaration de la classe.

Cette technique est surtout intéressante en C et beaucoup moins
justifiée en C++ puisque l'on peut stocker les données dans la classe
représentant la fenêtre plutôt que dans la structure système gérant
cette fenêtre.

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Avatar
Stephane Legras-Decussy
Patrick Philippot a écrit dans le message
: d1m410$28ih$
Pour les données associées/associables à une fenêtre ou une classe de
fenêtre et qui doivent pouvoir être récupérées à tout moment,
j'ajouterai aux réponses précédentes la possibilité de stocker avec
chaque structure de fenêtre ou chaque structure de classe des données
privées que vous pouvez gérer avec SetWindowLong et GetWindowLong à
l'offset GWL_USERDATA. Il faut simplement penser à réserver l'espace
nécessaire dans les champs cbClsExtra et cbWndExtra au moment de la
déclaration de la classe.



ah oui, ça semble assez séduisant comme technique...

merci !
1 2 3