Faut-il utiliser le préfixe « m. » devant les noms de variable? Eternelle question. Lorsque VFP rencontre dans une expression un nom qui peut être interprété comme une variable ou comme le champ d’une table, il résout l’ambiguïté en donnant priorité au champ de la table. Si l’objectif est de produire du code robuste, la réponse est évidemment OUI, il faut préfixer les variables par « m. » dans tous les cas où la variable est utilisée. Microsoft ne respecte pas toujours cette règle. Il est par exemple très facile de planter le Browser de classe. Pour vous en persuader tapez cette commande dans la fenêtre de commande : create cursor CCC( tllistBox C(10)) puis lancez le « Class Browser » à partir du menu de VFP vous obtiendrez l’erreur : Function argument value, type or count is invalid Pour comprendre ce qui se passe, décompressez xsource.zip qui se trouve dans le répertoire Tools, vous trouverez dans VFPSource\Browser\Browser.prg à la ligne 40 le code suivant : IF tlListBox AND tlGallery MESSAGEBOX(M_LISTBOX_MODE_ERROR_LOC+".",48,M_COMPONENT_GALLERY_LOC) Les variables (qui sont ici des paramètres de la procédure) ne sont pas préfixées par « m. », c’est le champ du cursor qui est pris. Il est de type caractère d’où l’erreur. S’il était de type logique l’erreur serait encore plus subtile car le programme serait faux sans déclencher d’erreur. J’ai souvent lu du code où les programmeurs pensaient que pour les objets il n’était pas indispensable de les préfixer par « m. ». Le petit bout de code suivant devrait les persuader du contraire. create Cursor Art( Libelle C(50) ) insert into Art values( "Libellé de la Table" ) Art = CreateObject("CArt") ? Art.Libelle ? m.Art.Libelle define class CArt as Custom Libelle = "Libellé de l'objet" enddefine Le résultat de ce morceau de code est : Libellé de la Table Libellé de l’objet Ma règle est la suivante, lorsque la variable est déclarée ou affectée je ne met pas le préfixe (c’est moins lourd à taper) et lorsqu’elle est utilisée je le met (par obligation), par exemple : local i i = m.i + 1 for i = 1 to m.Limite Si l’on remarque qu’il n’est pas possible de créer un champ dont le nom commence par « _ » on peut aussi utiliser des variables dont le nom commence par « _ » sans les préfixer par « m. » car l’ambiguïté n’est plus possible. J’espère qu’il ne viendra à l’idée de personne d’appeler un objet m ! En fait cela est possible, exemple : local nom local m nom = "Nom dans variable" m = CreateObject( "MaClasse" ) ? Nom ? m.Nom ? m.m.Nom define class MaClasse as Custom nom = "Nom dans objet" enddefine Donne le résultat suivant : Nom dans variable Nom dans variable Nom dans objet En fait dans ce cas si l’on désire affecter une valeur à la propriété Nom de l’objet m il faut écrire : m.m.Nom = "Nouveau Nom dans objet" Tout autre écriture affecterait la variable Nom et non la propriété de l’objet m ! Il est à mettre au crédit de VFP que l’alias « M » est interdit. Sinon … Mais l’alias « This » est parfaitement légal. Exemple : create table THIS( X C(10)) insert into THIS values( "From Table" ) oSympa = CreateObject( "Sympa" ) ? oSympa.F1() ? oSympa.F2() define class Sympa as Custom X = "from Object" function F1 return this.X && syntaxe à risque endproc function F2 return m.this.X && syntaxe blindée endproc enddefine Donne le résultat suivant : From Table From Object C’est la même chose avec « ThisForm ». Exemple : create table thisform( X C(10)) insert into thisform values( "From Table" ) oSympa = CreateObject( "FormSympa" ) ? oSympa.F1() ? oSympa.F2() define class FormSympa as Form X = "from Object" function F1 return thisform.X endproc function F2 return m.thisform.X endproc enddefine Donne le même résultat que précédemment. Or dans les FFC « m. » n’est utilisé ni devant this ni devant thisform. On peut donc faire planter les FFC très facilement. Pour terminer sur ce sujet inépuisable, il est vrai que si tout le monde utilise des conventions de dénomination stricte pour les champs, les variables et les objets, ces cas d’ambiguïté ne devraient pas se produire, mais peut-on appuyer une production de code robuste sur une telle hypothèse ? Je laisse la réponse au lecteur. |
Bonsoir Robert,
j'ai bien aimé ta réflexion sur ce sujet,
et les exemples sont clairs et complets,
je me permet : d'ajouter un peu d'eau à ta fontaine :
pour ma part :
- une variable préfixée d'un "_" est effectivement forcement une variable ,
mais je suggère : de ne pas de généraliser son emploi.
en effet il existe déjà des variables vfp de portée "public" / "globale" aux programmes codifiée sur cette forme. Leurs usages doivent être gardées à ce niveau me semble t il , donc une utilisation : trés modeste dans son ensemble.
- dans notre paroisse nous avons "conventionné" la chose suivante : toutes nos varibales sont préfixées de "v_" et il est interdit de créer un champ commençant par le même préfixe. De ce fait nous n'avons aucun problème. un peu de rigueur et la "liberté" que nous donne vfp est bien gérée.
- enfin tu ne parles pas de l'écriture elle même,
en effet il me semble important qu'un programme puisse être maintenu par plusieurs personnes, et donc puisse "re lire" clairement et sans ambiguité grâce de petite régles simples : aussi si les variables sont toujours préfixées "v_" (chez nous !!) les champs sont écrit en majuscules et de préférence avec le nom de l'alias. cela rend la lecture aisée et enlève les "doutes" de l'interpréteur vfp..
donc nous n'écrirons jamais :
for i=1 to 10
relace nombre with str(i)
abc = truc
...... mais
for v_i=1 to 10
replace NOMBRE with str(v_i)
v_abc = CLIENT.TRUC
la lisibilité des programmes est accrue, gain de temps...
Cordialement
Francis FAURE