5

ColdFusion コンポーネント (CFC) では、変数スコープの変数に完全修飾名を使用する必要がありますか?

これを変更すると、問題が発生するのでしょうか。

<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>

これに?

<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>
4

9 に答える 9

10

foo はデフォルトで変数スコープに配置されるため、変数を作成するときに「変数」を指定しても問題ありません。ただし、変数にアクセスするときは問題になります。

<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") は、「 args関数ローカル変数があります」を返します。

doAnotherThing("args") は、「変数のプライベート インスタンス関数ローカル変数があります」を返します。

于 2008-09-12T17:22:31.873 に答える
6

はいと答えます。明示的に必要ですか?いいえ。やらないと逃げられますか?もちろん。トラブルを求めていますか?絶対。cffunction 内に以下がある場合:

<cfset foo = "bar" />

これにより、その変数は関数のローカル var スコープに配置されず、CFC のグローバル VARIABLES スコープに配置されます。つまり、その CFC のすべてのメソッドで使用できるようになります。これを行いたい場合もありますが、ほとんどの場合、競合状態を要求することになります。

サーバーが変数を読み取るときに、その変数がスコープ (REQUEST.、SESSION. など) の一部として明示的に宣言されていない場合、ColdFusion は ScopeCheck() を実行して、変数がどのスコープにあるかを判断します。これにより、アプリケーションサーバーに不要なオーバーヘッドが発生します。また、変数が1つのスコープ内にあるハイジャックの機能が導入されますが、ScopeCheck() は優先順位が高い同じ名前の変数を検出しました。

常に、常に、常に、すべての変数のスコープを設定します。どんなに些細なことでも。クエリ名やループ インデックスなども含まれます。あなた自身とあなたの後ろにいる人たちを痛みから救いましょう。

于 2008-09-24T18:14:17.897 に答える
5

特に CFC では、適切な範囲設定が重要です。余分な「冗長性」は、明確にする価値があります。変数が意図したスコープから外れると、重大な問題が発生し、診断が非常に困難になります。

冗長性は必ずしも悪いことではありません。関数とメソッドの名前は、gau() ではなく、getAuthenticatedUser() のようにわかりやすい方法で命名します。データベースの列とテーブルは、emprl ではなく EmployeePayroll のようにわかりやすいものにしておくのが最善です。したがって、短期記憶がプロジェクトの詳細でいっぱいの場合は、簡潔にする方が「簡単」かもしれませんが、説明的であると意図が示され、短期記憶が他のものでいっぱいになってからずっと後のアプリケーションのメンテナンス段階で役立ちます。 .

于 2008-09-15T17:52:33.993 に答える
3

あなたの質問に対する簡単な答えは、いいえ、そうしようとしてもおそらく問題に遭遇することはないでしょうということです。UDF のコンテキスト外 (CFC 内であっても) では、スコープのない set ステートメントは、変数のスコープを意味します。

さらに、CFC では、Variables スコープをそのすべての関数で使用できます。これは、その CFC 内の一種のグローバル スコープです。「this」スコープに似ていますが、変数スコープは「プライベート」変数に似ているのに対し、this スコープはパブリック変数に似ています。

これをテストするには、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>

そしてそれをテストするためのページ、test.cfm:

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

結果は次のようになります。


さて、あなたのサンプルコードに見られる別の問題に対処するために...

CF では、すべてのユーザー定義関数に、一般に「var」スコープと呼ばれる特別な名前のないスコープがあります。UDF 内で次の操作を行う場合:

<cfset foo = "bar" />

次に、その変数を var スコープに入れるように CF に指示しています。

事態を少し複雑にするために、インライン UDF で var スコープを使用していないときに、問題 (予期していなかったときに変数値が変化する) に遭遇する可能性があります。

したがって、経験則は、常に、常に、常に、常に、関数内部変数 (クエリ名を含む) を var-scope にすることですvarScoperというツールがあり、var-scoped が必要な変数を見つけるのに役立ちます。最後に、完璧ではないことを確認しましたが、間違いなく始まりです。

ただし、CFC または標準の CFM ページでさえ、スコープなしで変数を参照 (表示/使用) することはお勧めできません (読み取り対象のスコープを指定できないため、明らかに var スコープの変数は除きます) CF7 の時点で、スコープを指定せずに変数を読み取ると、特定の順序でチェックされる 9 つのスコープがあり、最初に一致したものが優先されます。CF8 では、そのリストにさらに多くのスコープがある可能性がありますが、私は確認していません。これを行うと、別のスコープから期待しているときに、あるスコープから値を取得するリスクがあります。これはデバッグするのに悪夢です...私はあなたを保証します。;)

要するに、変数のスコープを (セット上で)暗示することは、悪い考えではありません (私は通常とにかくそれを指定しますが)。しかし、変数のスコープを(読み取り時に)推測すると、問題が発生します。

于 2008-09-12T17:27:14.343 に答える
2

変数スコープで明示的にスコープしないことはうまくいくかもしれませんが、それは良い考えではありません。すべてを明示的にスコープすると、1) 潜在的な問題を回避できます。また、2) どのスコープにあるかに疑問がないため、コードが読みやすくなります。

私にとっては、コードがより冗長になることはありません (そして確かに不必要に冗長ではありません)。実際には読みやすくなり、混乱を避け、明示的にスコープを設定しない場合に発生する可能性のある奇妙な副作用を回避できます。

于 2008-09-29T12:04:25.797 に答える
1

あなたの質問に対する簡単な答えは、「いいえ、それは必要ありません」です。

ただし、ベストプラクティスでは、実際には、これらの変数にアクセスするときに変数識別子を使用することをお勧めします。私の意見では、将来あなたのコードに出くわし、関数の真ん中を見ている人は誰でも、関数の上部をローカル関数でスキャンしなくても、変数のスコープを即座に知ることができます。

実際、1つのローカル構造体を作成することにより、CFCUDFに少し冗長性を追加します。

<cfset var local = structNew()/>

次に、すべてのローカル変数をその構造体に配置し、そのように参照して、コードが次のようになるようにします。

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

于 2008-09-15T13:44:20.890 に答える
0

あなたの答えを読んだ後、私が考えていることは次のとおりです。

はい、安全です。一般に、変数スコープを明示的に指定する必要はありません。すでに冗長な言語に混乱を加えるだけです。

確かに、 Soldarnalが指摘したように、変数スコープの変数を修飾する必要があるという小さな例外が1つあります。これは、同じ名前の関数ローカル変数がある場合です。(しかし、とにかくそうすべきではないでしょう。)

于 2008-09-12T20:38:06.553 に答える
0

ベスト プラクティスはさておき、CFC にアクセスする方法にもよると思います。オブジェクトを作成して Coldfusion からアクセスするときに、それらを除外しても問題はありませんでした。ただし、フレックス/フラッシュのアクションスクリプトを介してリモートでアクセスおよび/またはマッピングする場合に必要になると思います。

于 2008-09-19T03:21:53.927 に答える
0

これは、Raymond Camdenによる非常に優れたCFC スコープ リファレンスです。個人的には、すべての混乱を避けるために「自己」ハッシュを作成することを好みます (関数で「変数」スコープを使用しないことに注意してください)。

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

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

  ...
于 2008-09-25T02:16:37.220 に答える