これは、私が 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>