15

ColdFusion のディレクトリ構造を再編成していますが、経験豊富な CF 開発者が小さな cffunctions のライブラリをどのように編成しているかに興味があります。

私は精巧なコンポーネント (オブジェクト) には興味がありませんが、時間の経過とともに構築される多数の小さなユーティリティ関数に興味があります。

  • cffunctions で大きな単一ファイルを使用し、それを cfinclude しますか?
  • 大きな単一ファイルを cfcomponent として使用し、creatobject/cfinvoke を呼び出しますか?
  • 各ユーティリティ cffunction を独自の cfc に入れ、createobject/cfinvoke を呼び出しますか?
  • cfimport taglib 構文を使用していますか?
  • CustomTags または cfmodule を使用していますか?
  • もっと良い方法はありますか?

私は冗長な構文が好きではないので、共通の cffunctions がたくさん含まれている lib.cfm を cfinclude するだけでした。変数スコープをより適切に分離するために、オブジェクトを作成できるグループ化された cfc にリファクタリングする場合があります。

これを行うより良い方法はありますか?

4

6 に答える 6

20

これは、私が 2007 年 6 月 13 日に行ったブログ投稿の再掲です。YMMV。

ユーザー定義関数 (UDF) が嫌いな人はいますか? プログラミングを行ったことがある場合は、それらを広範囲に使用している可能性があります。人々が抱える最大の問題は、アプリケーションにそれらを含めて整理する方法です。

ほとんどの人が行っていることは、Utils.cfc または UDFs.cfc を作成し、以下に示すように、使用したい UDF をカット アンド ペーストすることです。

<!--- UDFs.cfc --->
<cfcomponent output="false">

<cffunction name="init" access="public” returntype="Any" output="false">
  <cfreturn this>
</cffunction>

<cffunction name="myUDF1" access="public" returntype="Any" output="false">
</cffunction>

<cffunction name="myUDF2" access="public" returntype="Any" output="false">
</cffunction>

</cfcomponent>

アプリケーションが使用するすべての UDF をコンポーネントに貼り付けたら、アプリケーションで UDF を使用できるようにする必要があります。私が見たほとんどの人は、このコンポーネントによるアプリケーション スコープへのロードを行っています。次の行は、 Application.cfc を使用しているonApplicationStart()場合は に配置されます。それを使用している場合は、Application.cfm に追加するだけです。

<cfset application.functions = CreateObject("component", "udfs").init()>

Application.cfc と Application.cfm のどちらを使用しても、結果は同じです。すべての UDF がアプリケーションで利用可能であり、全体を通して自由に使用できます。唯一の違いは、使用する変数名です。私は application.functions を使用しますが、application.utils または application.udfs を使用する人もいます。繰り返しますが、結果は同じです。

ただし、このアプローチには 1 つの問題があります。それは面倒であり、UDF コンポーネントが巨大になることです。このような巨大なコンポーネント ファイルを持つことの問題は、何千行ものコードをスクロールするのはあまり楽しくないため、編集が悪夢になることです。また、巨大なファイルでは CFEclipse が動かなくなることにも気付きました。確かにコードを折りたたむことである程度の緩和が得られますが、もっと良い方法が必要です。

私が望んでいたのは、使用している UDF ごとに 1 つのファイルだけを用意し、アプリケーションがそれらを自動的にロードする方法を提供することでした。この背後にある理由は、編集する必要がある場合にmyUDF1、ファイルmyUDF1.cfmを開いて必要なものを編集できるようにするためでした。また、 CFLib.orgから UDF を取得して、何も編集せずにアプリケーションにドロップできるようにしたいと考えていました。アプリケーションから UDF を削除する必要が生じた場合は、UDF ファイルを削除してアプリケーションを再初期化するだけで済みます。

目的を達成するために、UDFs.cfc を 11 行のコードに変更しました。

<!--- UDFs.cfc --->
<cfcomponent output="false">

  <cfset variables.udfdir = GetDirectoryFromPath(GetCurrentTemplatePath()) & "udfs">
  <cfset variables.q = "">

  <cffunction name="init" access="public" returntype="Any" output="false">
    <cfreturn this>
  </cffunction>

  <cfdirectory action="list" directory="#variables.udfdir#" filter="*.cfm" name="variables.q">

  <cfoutput query="variables.q">
    <cfinclude template="udfs\#name#">
  </cfoutput>

</cfcomponent>

それで、正確に何が起こっているのですか?

簡単に言うと、何が起きているかというとudfs、UDFs.cfc があるディレクトリと同じディレクトリに、という名前のディレクトリがあります。これは、すべての UDF CFM ファイルを置いたディレクトリです。UDFs.cfc は、呼び出されたときにこのディレクトリをスキャンし、検出した各 CFM ファイルを自動的に含めます。したがって、UDFs フォルダー内のすべての UDF をそれ自体に自動的にロードします (一般に "mixin" と呼ばれます)。

だから私の目標は達成されました!各 UDF は独自のファイルに格納されているため、巨大なコンポーネント ファイルをスクロールして検索する必要はありません。簡単に開いて編集できるようになりました。ディレクトリを見るだけで、アプリケーションがどの UDF を使用しているかがわかります。ブラウザからテキストをディレクトリ内のファイルに保存するだけで、CFLib.org から UDF を自動的に追加できます。さらに、アプリケーションで UDF を使用する必要がなくなった場合は、ディレクトリからファイルを削除するだけで、次の再初期化時にアプリケーションから削除されます。これはすべて、メインの UDFs.cfc ファイルに触れることなく実行できます。

以下は、UDF CFM ファイルの 1 つがどのように見えるかの例です。ファイルが呼び出さfullLeft.cfmれ、UDFs ディレクトリに置かれます。

<!--- fullLeft --->
<cffunction name="fullLeft" access="public" displayname="fullLeft" returntype="string" output="false">
  <cfargument name="str" type="string" required="true">
  <cfargument name="count" type="numeric" required="true">
  <cfif not refind("[[:space:]]", arguments.str) or (arguments.count gte len(arguments.str))>
    <cfreturn Left(arguments.str, arguments.count)>
  <cfelseif reFind("[[:space:]]",mid(arguments.str,arguments.count+1,1))>
    <cfreturn left(arguments.str,arguments.count)>
  <cfelse>
    <cfif count-refind("[[:space:]]", reverse(mid(arguments.str,1,arguments.count)))>
      <cfreturn Left(arguments.str, (arguments.count-refind("[[:space:]]", reverse(mid(str,1,arguments.count)))))>
    <cfelse>
      <cfreturn left(arguments.str,1)>
    </cfif>
  </cfif>
</cffunction>
于 2009-03-09T02:02:01.680 に答える
1

これはあなたのプログラミングスタイルに依存すると思います。あなたが最も快適なスタイルを選んでください。最も簡単な方法はapplication.cfmにあり、アプリケーションスコープの変数をすべてのユーティリティ関数でcfcomponentに設定します。

<cfif not isDefined("application.utilities")>
    <cfset application.utilities = createObject("component", "Utilities")>
</cfif>

これで、どこからでもapplication.utitliesのメソッドを呼び出すことができます。cfcomponentに変更を加える場合は、Utilitiesの新しいインスタンスでアプリケーション変数を更新する必要があることに注意してください。

于 2009-03-09T01:17:35.843 に答える
1

関数ライブラリには .cfm ファイルを使用し、cfinclude で適切なファイルを呼び出します。.cfm ファイルの一部は cflib.org からダウンロードされ、その他は私たちが作成したものです。ファイルは、スラッシュ文字にマップされた別のディレクトリのサブディレクトリである UDF という名前のディレクトリにあります。cfinclude ステートメントは単純です。

<cfinclude template="/UDF/filename.cfm">

このアプローチにより、サーバー上のすべてのアプリケーションで関数を使用できるようになります。

また、いくつかの小さなライブラリのアプローチを好みます。各ライブラリはトピック固有です (数学、文字列、リスト配列など)

于 2012-11-18T14:55:33.167 に答える
1

Application.cfc を使用している場合 (そうでない場合は、Application.cfm から移行することを強くお勧めします。非常に簡単です)、すべての UDF メソッドを使用して baseComponent.cfc を構築し、Application.cfc を継承させることができます。ベース コンポーネント。次に、onRequestStart メソッドで、request.app=this; という変数を設定します。

リクエスト全体に対して、request.app.methodname() を使用して UDF にアクセスできます。UDF を処理する非常に優れたシンプルな方法

また、必要に応じて、すべての cfc が同じ baseComponent から継承するようにして、すべての cfc がこれらのユーティリティ関数をネイティブ メソッドとして持つようにすることもできます。Cfc は UDf コンポーネントへの渡された (挿入された) 参照に応答する必要がないため、cfc の単体テストが非常に簡単になります。

このアプローチの課題の 1 つは、cfc の extends 属性を式にすることができないことです。そのため、コンポーネントをパッケージ化する方法によっては、これを実装するのが難しい場合があります。これを処理する最も簡単な方法は、coldfusion マッピングを使用することです。

h番目のジョン

于 2009-03-27T21:50:10.053 に答える
0

これは古い質問だと思いますが、これらの問題に対して少し異なるアプローチを使用します。

ユーティリティ関数/「注入」によるシングルトン アプローチ

「コア」または「ユーティリティ」cfc を作成します。その中に、次のすべてのユーティリティ タイプ関数をパックします。

  • いつでもどこでも頻繁に使用されます (ジェネリックviewRecord()dao やコアcheckSecurity()関数など)。
  • 私見がCFのコアであるべき基本機能です(、、lpad()などcapitalize()
  • cfscriptどこでも使用できるいくつかのタグのラッパーです( exit()which wrapsなど<cfexit>

onApplicationStart()で、このオブジェクトのインスタンスを作成し、それをスコープに割り当てて、Application一種の静的シングルトンを作成します。

次に、これをほぼすべての cfc に拡張または再インクルードする代わりに、より伝統的なタイプの継承に拡張機能を使用できるようにし、構築するすべての cfc のコンストラクター (init) にこれらのメソッドを挿入します。これを行うには、次のようにユーティリティ オブジェクト自体でメソッドを呼び出します。

public/remote any function init() {
  structAppend( Variables, Application.MyApp.Objects.oCore.injectCoreMethods() ); 
  return this; // Return instance of this object
}

このinjectCoreMethods()メソッドは、すべてのオブジェクトに仮想的に拡張したいユーティリティ関数の構造を選択的に返します。必ずしもすべてのユーティリティ メソッドを注入するわけではありません。injectCoreMethods()それ自体を含め、あまり使用されないものは、Application.MyApp.Objects.oCore.infrequentMethod().

保護されているスコープに注入することによりVariables、これらのメソッドは効果的にプライベート メソッドになります。そのため、オブジェクトのダンプにはこれらのユーティリティ関数は表示されませんが、すべてのダイレクト メソッドによって cfc 内で完全にアクセスできます。

ファイル編成:

私は通常、フォルダごとに 1 つの CFC を持つというパターンに陥っています。各フォルダーには、コンポーネントと init 用の cfc ファイルが 1 つあります。他のすべての方法は、cfm ファイルに分けて、その cfc に含めます。私はこれを行う:

  1. IDE の速度を低下させる可能性のある 1000 行以上の巨大な cfc ファイルを回避します (aptana/cfeclipse を使用しています)。
  2. 変更をファイルごとに個別に記録/追跡できるようにして、SCM/バージョン管理ソフトウェアに記録します。
  3. 互いにコードを衝突させることなく、複数の人が特定のオブジェクトで作業できるようにします。

したがって、4 つの crud メソッドを含む dao オブジェクトは次のようになります。

/code/dao/dao.cfc
/code/dao/_removeRecord.cfm
/code/dao/_addRecord.cfm
/code/dao/_viewRecord.cfm
/code/dao/_editRecord.cfm

init()CFC にはと の自己文書化コメントだけが含まれており、疑似コンストラクター領域には 4 つのメソッドが含まれています。これにより、任意の cfc をそのフォルダーごとに取得して、どこかに移動することもできます。

ユーティリティ cfc についても同じです。それは独自のフォルダーにあり、10 ほどの cfm ファイルの中に約 30 の奇妙な関数があります (_string.cfm実際にはlpad()rpad()などのすべての文字列に関連するものなど、同じファイルにいくつかの単純な関数を残します。おわかりいただけると思います。)

モジュールとカスタム タグ

これらは登録する必要があり、簡単な移動/展開を妨げるため、私はこれらを絶対に避けます。ある環境から別の環境へのドラッグアンドドロップで自己構成するだけではないものは好きではありません。CF5-あなたはこの方法でもっと多くのことをしなければなりませんでした. しかし、CF6 と実際の OOP パターンでオブジェクトを使用する機能があるため、なぜそうしたいのでしょうか? あなたが望む/必要とするケースはほとんどありません。

他の

以前は「コア」関数を base.cfc に入れていましたが、これは CF によって生成されたすべての cfc に自動的に拡張されます (探して、関数を追加すると出来上がりです! js でプロトタイプに何かを追加するようなものです)。私はこれが本当に好きでしたが、展開/メンテナンスの問題でした.

ある程度、私は工場のアプローチを取ります。私はよく、コアのようなアプリケーションにかなりの量の静的 CFC を配置します。コントローラーは、一般的な制御テーブルを読み取り、ループ内のすべてのオブジェクトを、アプリの変数など、アプリの開始時にさまざまなものと共に設定します。ただし、一部のオブジェクトは必要に応じてインスタンス化されます。明らかに重いオブジェクトや、操作可能な [半] 永続データを含むオブジェクトは、そのカテゴリに分類されます。

私は、ある意味で、CF7 以来これを行ってきました。CF9+ では、非常に簡単で、成熟した、洗練されたものになっています。

于 2013-06-06T01:43:39.680 に答える
0

オプション: cffunctions で大きな単一ファイルを使用し、それを cfinclude しますか?

A: 私はそれをしましたが、ますます少なくしています。継承と cfcexplorer を利用するのが好き

オプション: 大きな単一ファイルを cfcomponent として使用し、creatobject/cfinvoke を呼び出しますか?

A: はい、私はよくこれを行います

オプション: 各ユーティリティ cffunction を独自の cfc に配置し、createobject/cfinvoke を呼び出しますか?

A: 後で追加機能が追加されると予想される場合は、これを行う可能性があります。

オプション: cfimport taglib 構文を使用しますか?

A: 私はそのように国際化を行っています

オプション: CustomTags を使用しますか

A: 久しぶりです。cfc の方が優れている

オプション: または cfmodule?

A: 久しぶりです。これに関しては、cfc の方が優れています。caller.* スコープはデバッグを困難にする可能性があります

于 2012-11-27T04:21:25.287 に答える