Fusion froide:Est-il prudent de laisser de côté le mot-clé variables dans un CFC ?

StackOverflow https://stackoverflow.com/questions/59390

  •  09-06-2019
  •  | 
  •  

Question

Dans un composant ColdFusion (CFC), est-il nécessaire d'utiliser des noms complets pour les variables de portée variable ?

Est-ce que je vais avoir des ennuis si je change ceci :

<cfcomponent>
    <cfset variables.foo = "a private instance variable">

    <cffunction name = "doSomething">
        <cfset var bar = "a function local variable">
        <cfreturn "I have #variables.foo# and #bar#.">
    </cffunction>
</cfcomponent>

pour ça?

<cfcomponent>
    <cfset foo = "a private instance variable">

    <cffunction name = "doSomething">
        <cfset var bar = "a function local variable">
        <cfreturn "I have #foo# and #bar#.">
    </cffunction>
</cfcomponent>
Était-ce utile?

La solution

Cela n'aura pas d'importance de spécifier des « variables » lorsque vous créez la variable, car foo sera placé par défaut dans la portée des variables ;mais cela aura de l'importance lorsque vous accéderez à la variable.

<cfcomponent>
    <cfset foo = "a private instance variable">

    <cffunction name="doSomething">
        <cfargument name="foo" required="yes"/>
        <cfset var bar = "a function local variable">
        <cfreturn "I have #foo# and #bar#.">
    </cffunction>

    <cffunction name="doAnotherThing">
        <cfargument name="foo" required="yes"/>
        <cfset var bar = "a function local variable">
        <cfreturn "I have #variables.foo# and #bar#.">
    </cffunction>

</cfcomponent>

doSomething("args") renvoie "J'ai arguments et un variable locale de fonction"

doAnotherThing("args") renvoie "J'ai une instance privée d'une variable et un variable locale de fonction."

Autres conseils

Je dirai oui.Est-ce explicitement nécessaire ?Non.Pouvez-vous vous en sortir sans le faire ?Bien sûr.Cherchez-vous des ennuis ?Absolument.Si vous avez les éléments suivants dans une fonction cf :

<cfset foo = "bar" />

Cela ne placera pas cette variable dans la portée var locale de la fonction, mais la placera dans la portée globale VARIABLES du CFC, ce qui signifie qu'elle est disponible pour chaque méthode de ce CFC.Il y a des moments où vous voudrez peut-être faire cela, mais la plupart du temps, vous demanderez une condition de concurrence.

Lorsqu'une variable est lue par le serveur, si cette variable n'est pas explicitement déclarée dans le cadre d'une portée (REQUEST., SESSION., etc.), ColdFusion exécutera ScopeCheck() pour déterminer dans quelle portée se trouve la variable.Non seulement cela entraîne une surcharge inutile sur votre serveur d'applications, mais cela introduit également la possibilité de piratage, dans lequel votre variable se trouve dans une seule portée, mais ScopeCheck() a trouvé une variable du même nom plus haut dans l'ordre de priorité.

Toujours, toujours, TOUJOURS, définissez la portée de toutes les variables.Aussi trivial soit-il.Même des choses comme les noms de requêtes et les index en boucle.Sauvez-vous, ainsi que ceux qui vous suivent, de la douleur.

En particulier dans le cas des CFC, une définition appropriée de la portée est importante.La « verbosité » supplémentaire vaut la clarté.Le fait que des variables sortent de leur portée prévue entraînera de graves problèmes et très difficiles à diagnostiquer.

La verbosité n'est pas toujours une mauvaise chose.Nous nommons nos fonctions et méthodes de manière descriptive comme getAuthenticatedUser(), plutôt que gau().Il est préférable de laisser les colonnes et les tables de la base de données de manière descriptive, comme EmployeePayroll plutôt que empprl.Ainsi, être concis peut être « plus facile » lorsque votre mémoire à court terme est pleine de détails du projet, mais être descriptif montre votre intention et est utile pendant la phase de maintenance d'une application, longtemps après que votre mémoire à court terme ait été remplie d'autres choses. .

La réponse courte à votre question est que non, vous n’aurez probablement aucune difficulté à tenter de le faire.En dehors du contexte d'une UDF (même toujours à l'intérieur d'un CFC), une instruction set sans portée implique la portée des variables.

De plus, dans un CFC, la portée Variables est disponible pour toutes ses fonctions ;c'est en quelque sorte la portée globale au sein de ce CFC - similaire à la portée "this", sauf que la portée des variables s'apparente à des variables "privées", alors que cette portée s'apparente à des variables publiques.

Pour tester cela, créez test.cfc :

<cfcomponent>
    <cfset foo = "bar" />
    <cffunction name="dumpit" output="true">
        <cfdump var="#variables#" label="cfc variables scope">
        <cfdump var="#this#" label="cfc this scope">
    </cffunction>
</cfcomponent>

et une page pour le tester, test.cfm :

<cfset createObject("component", "test").dumpit() />

Et les résultats seront :


Maintenant, pour résoudre un autre problème que je vois dans votre exemple de code...

Dans CF, toutes les fonctions définies par l'utilisateur ont une portée spéciale sans nom communément appelée portée « var ».Si vous effectuez les opérations suivantes dans une UDF :

<cfset foo = "bar" />

Ensuite, vous dites à CF de mettre cette variable dans la portée var.

Pour aggraver un peu les choses, vous pouvez rencontrer des problèmes (les valeurs des variables changent alors que vous ne vous y attendiez pas) lorsque vous êtes pas en utilisant la portée var dans vos UDF en ligne.

La règle générale est donc de toujours, toujours, TOUJOURS, TOUJOURS var-scope vos variables internes à la fonction (y compris les noms de requêtes).Il existe un outil appelé varScoper cela vous aidera à trouver les variables qui doivent être de portée variable.La dernière fois que j'ai vérifié, ce n'était pas parfait, mais c'est définitivement un début.

Cependant, c'est un mauvais idée de référencer (afficher/utiliser) des variables sans portée (à l'exception évidemment des variables à portée variable, car vous ne pouvez pas spécifier la portée à partir de laquelle lire) dans les CFC ou même sur vos pages CFM standard.Depuis CF7, 9 étendues étaient vérifiées dans un ordre spécifique lorsque vous lisez une variable sans spécifier la portée, la première correspondance l'emporte.Avec CF8, il pourrait y avoir plus de scopes dans cette liste, je n'ai pas vérifié.Lorsque vous faites cela, vous courez le risque d'obtenir une valeur d'une étendue alors que vous l'attendez d'une autre ;ce qui est un cauchemar à déboguer...Je t'assure.;)

Donc en bref : impliquant la portée d'une variable (sur le plateau) n'est pas une mauvaise idée (même si je la précise habituellement de toute façon) ;mais déduire la portée de la variable (en lecture) pose problème.

Ne pas définir explicitement la portée des variables peut fonctionner, mais ce n'est pas une bonne idée, et honnêtement, c'est la seule raison. pas c'est par paresse, OMI.Si vous délimitez explicitement tout 1) vous évitez les problèmes potentiels et 2) cela rend le code plus facile à lire car il ne fait aucun doute dans quelle portée se trouvent les choses.

Pour moi, cela ne rend pas le code plus verbeux (et certainement pas inutilement verbeux) - il est en fait plus facile à lire, évite toute confusion et évite les effets secondaires étranges qui peuvent survenir si vous ne le précisez pas explicitement.

La réponse simple à votre question est :"NON, ce n'est pas nécessaire"

Cependant, je pense que les meilleures pratiques suggèrent que vous utilisiez en fait l'identifiant de variables lorsque vous accédez à ces variables.À mon avis, quiconque tombera sur votre code à l'avenir et regardera au milieu d'une fonction connaîtra instantanément la portée de la variable sans avoir à scanner le haut de la fonction et les fonctions locales.

En fait, j'ajoute un peu plus de verbosité à mes UDF CFC en créant une structure locale :

<cfset var local = structNew() />

Ensuite, je mets toutes mes variables locales dans cette structure et je les référence de cette façon pour que mon code ressemble à ceci :

<cfset local.foo = variables.bar + 10 />

Après avoir lu vos réponses, voici ce que je pense :

Oui, c'est sûr.En général, il n'est ni nécessaire ni utile de spécifier explicitement la portée des variables.Cela ne fait qu'ajouter du désordre à un langage déjà verbeux.

Certes, il existe une exception mineure, comme Soldat souligné, où la qualification d'une variable de portée variable est requise.C'est si vous avez une variable locale de fonction avec le même nom.(Mais vous ne devriez probablement pas faire ça de toute façon.)

Mis à part les meilleures pratiques, je pense que cela pourrait également dépendre de la manière dont vous allez accéder à vos cfc. Je n'ai eu aucun problème à les laisser de côté lors de la création d'objets et d'y accéder depuis Coldfusion.Cependant, je pense que cela pourrait être nécessaire pour y accéder et/ou les mapper à distance via actionscript dans flex/flash.

Voici un très bon Référence du périmètre CFC de Raymond Camden.Personnellement, je préfère faire un hachage 'self' pour éviter toute confusion (remarquez que je n'utilise pas la portée 'variables' dans les fonctions) :

<cfcomponent>
  <cfset variables.self = structNew()>
  <cfscript>
    structInsert(variables.self, <key>, <value>);
    ...
  </cfscript>

  <cffunction name="foo">
    self.<key> = <value>
    <cfreturn self.<key> />
  </cffunction>

  ...
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top