プロジェクトメソッド

4D - Documentation   French   English   German   Spanish   日本語   4D v11 SQLコマンドテーマリスト   4D v11 SQLインデックス   4D v11 SQL定数テーマリスト   戻る   前   次

version 6.0


プロジェクトメソッドには、適切な名前を付ける必要があります。フォームメソッドやオブジェクトメソッドはフォームやオブジェクトと密接に関連付けられていますが、プロジェクトメソッドはどこにでも使用できます。データベースの特定のオブジェクトに付属しているわけではありません。プロジェクトメソッドはその実行方法や使用方法に応じて、次のような役割を果たします:

・メニューメソッド

・サブルーチン、関数

・プロセスメソッド

・イベント処理メソッド

・エラー処理メソッド

これらの用語はプロジェクトメソッドを、それがなんであるかで識別するのでなく、何を行うで識別しています。

メニューメソッドは、カスタムメニューから呼び出されるプロジェクトメソッドです。これは、ユーザのアプリケーションの流れを管理します。メニューメソッドは、必要とされる場所での分岐、フォームの表示、レポートの生成、ユーザデータベースの一般的な管理といった制御を行います。

サブルーチンは、処理の下請け的なプロジェクトメソッドです。他のメソッドから呼ばれて、リクエストされた処理を実行します。関数は、呼び出し元のメソッドに値を返すサブルーチンです。

プロセスメソッドは、プロセスの開始時に呼び出されるプロジェクトメソッドです。このプロセスは、プロセスメソッドが実行されている間だけ存続します。プロセスに関する詳細はプロセスの節を参照してください。メニューに属するメニューメソッドのプロパティとして新規プロセス開始をチェックした場合も、プロセスメソッドとして開始されます。

イベント処理メソッドは、イベントを処理するプロセスメソッドとして、分離されたプロセス内で実行されます。通常、開発者はイベント管理の大部分を4Dに任せます。例えば、データ入力中、4Dがキーストロークやクリックを検出し、それから正しいオブジェクトとフォームメソッドを呼び出します。このため開発者は、これらのメソッド内でイベントに対し適切に応答できるのです。一方、開発者がイベントを直接操作したい場合があります。例えば(レコードをブラウズするFor...End forループ等)処理時間の長い操作を実行する場合、「Ctrl+.(ピリオド)」キー(Windows)や「command+.(ピリオド)」キー(Macintosh)を押して、その操作への割り込みを行いたいとします。この場合、開発者はイベント処理メソッドを使用する必要があります。詳細はON EVENT CALL コマンドの説明を参照してください。

エラー処理メソッドは、割り込みを実行するプロジェクトメソッドです。エラーや例外が起こる度に、エラー管理メソッドがインストールされたプロセス内で実行されます。詳細はON ERR CALL コマンドの説明を参照してください。

メニューメソッド


アプリケーションモードでカスタムメニューを選択すると、そのメニューに関連付けられたメニューメソッドが実行されます。メニューエディタを使用して、メニューコマンドにメソッドを割り当てます。メニューが選択されると、それに対応するメニューコマンドが実行されます。この手順は、データベースをカスタマイズする主要な方法の一つです。特定の処理を実行するメニューメソッドを割り当てたカスタムメニューを作成することで、データベースをカスタマイズすることができます。詳細は、4D Design Referenceのメニューエディタの説明を参照してください。

カスタムメニューコマンドにより、単一または複数の処理を実行することができます。例えば、データの入力処理を実行するメニューは、以下の2つの処理を実行するメソッドを呼び出すことができます。まず適切な入力フォームを表示します。次にユーザがキャンセルするまでの間ADD RECORD コマンドによるデータ入力を繰り返します。

連続した処理の自動化は、プログラミング言語の強力な機能の1つです。カスタムメニューを使用すると、処理を自動化することができ、データベースのユーザにより多くのガイダンスを提供することができます。

サブルーチン


プロジェクトメソッドを作成すると、それは同じデータベースシステムの言語の一部になります。プロジェクトメソッドは、4Dに組み込まれたコマンドと同様に呼び出すことができます。このように使用されるプロジェクトメソッドをサブルーチンと呼びます。

サブルーチンは、以下のようなメリットがあります。

・重複したコードをなくす

・メソッドの役割を明確にする

・メソッドの変更を容易にする

・コードをモジュール化する

例えば、顧客データベースがあるとします。データベースをカスタマイズしていくうちに同じ処理を繰り返し行うことに気づいたとします。それは顧客を検索してレコードを修正するという一連の作業です。そのコーディングは以下のようになっています:

      ` 顧客を検索
   QUERY BY EXAMPLE([Customers])
      ` 入力フォームを選択
   INPUT FORM([Customers];"Data Entry")
      ` 顧客のレコードを修正
   MODIFY RECORD([Customers])

サブルーチンを使用しなければ、顧客レコードの修正を実行するたびにコードを作成しなければなりません。10箇所で同じ処理が必要になると、同じコーディングを10回も行わねばなりません。サブルーチンを使用すれば1回コーディングするだけで済みます。これがコーディングの重複をなくすというサブルーチンの第一の利点です。

先ほど説明したコードがMODIFY CUSTOMERと呼ばれるメソッドであるならば、他のメソッドの中でメソッドの名前を使って実行できます。例えば、顧客のレコードを修正し、それからレコードをプリントするために、以下のようなメソッドを書くことができます:

   MODIFY CUSTOMER
   PRINT SELECTION([Customers])

この機能はメソッドを劇的にに簡素化します。例においてMODIFY CUSTOMERメソッドがどのように動作するか知る必要がなく、何を行うかを知っていればよいのです。これは、メソッドをサブルーチン化にすることにより処理内容が明確になる、二番目のメリットです。また、これにより作成したメソッドは4D言語を拡張したことになります。

このデータベース例で、顧客を検索する方法を変更する必要がある場合、10か所ではなく、たった1つのメソッドを変更するだけで済みます。これがサブルーチンを使うもう一つの理由です。

サブルーチンを使ってコードをモジュール化します。これはコードをモジュール(サブルーチン)に分割することを意味し、それぞれは論理的な仕事を実行します。アカウントデータベースの以下のコードを見てみましょう:

   FIND CLEARED CHECKS   ` 決済済みの小切手を見つける
   RECONCILE ACCOUNT   ` 口座の照合
   PRINT CHECK BOOK REPORT   ` 出納記録の印刷

データベースを知らない人でも、このプログラムが何をしているかはわかります。各サブルーチンの処理手順を知る必要はありません。各サブルーチンは長く、複雑な処理で構成されていることもありますが、そのサブルーチンが何を実行するのかだけを知っていれば十分です。

プログラムを論理的な処理単位やモジュールにできるだけ分割することをお勧めします。

メソッドに引数を渡す


メソッドにデータを渡す必要がしばしば発生します。これは引数によって容易にできます。

引数は、メソッド内で行う処理に必要なデータです。引数という用語はこのマニュアルの随所で使用されています。引数は、4Dコマンドへデータを渡す場合にも使用します。以下の例は、文字列“Hello”という引数をALERTコマンドへ渡します:

   ALERT("Hello")

引数は、メソッドに対しても同じように渡すことができます。例えばメソッドDO SOMETHING が3つの引数を受け取る場合、このメソッドを呼び出すには以下のように書きます:

   DO SOMETHING(WithThis;AndThat;ThisWay)

引数は、セミコロン (;) で区切ります。

サブルーチン (呼び出されるメソッド) 内で、それぞれの引数の値は自動的に、順に番号が付けられたローカル変数 ($1, $2, $3...) に格納されます。ローカル変数の番号は、引数の順序を表わします。

このローカル変数/引数は呼び出しメソッドから渡された実際のフィールドや変数、式ではなく、渡された値を保持しているだけです。

サブルーチン内で、他のローカル変数と同様にこれらの引数 ($1, $2...) を使用できます。

Note: しかしながら、引数として渡した変数の値を変更するコマンドを使用する場合 (例えばFind in field)、$1, $2などの直接使用することはできません。まず標準のローカル変数等にコピーする必要があります (例: $myvar:=$1)。

引数はローカル変数であるため、サブルーチン内でのみ使用可能で、サブルーチンの終了時にクリアされます。このためサブルーチンは、引数として渡された実際のフィールドや変数の値を呼び出しメソッドレベルで変更できません。例えば:

      ` MY METHODメソッド
   DO SOMETHING ([People]Last Name) ` [People]Last Nameの値が"williams"だとします
   ALERT([People]Last Name)

      ` DO SOMETHINGメソッド
   $1:=Uppercase($1)
   ALERT($1)

DO SOMETHINGが表示するアラートボックスには“WILLIAMS”と表示され、MY METHODが表示するアラートボックスには“williams”と表示されます。メソッドは引数$1の値をローカルに変更します。しかしこの変更はMY METHODで引数として渡されたフィールド [People]Last Nameの値に影響しません。

メソッドDO SOMETHINGでフィールドの値を変更する方法には2通りあります:

1. メソッドにフィールドを渡すのではなく、フィールドへのポインタを渡します:

      ` MY METHODメソッド
   DO SOMETHING (->[People]Last Name) ` [People]Last Nameの値が"williams"だとします
   ALERT([People]Last Name)

      ` DO SOMETHINGメソッド
   $1->:=Uppercase($1->)
   ALERT($1->)

ここで、引数はフィールドではなく、フィールドへのポインタです。DO SOMETHINGメソッド内では、$1はフィールドの値ではなく、フィールドへのポインタです。$1参照されるオブジェクト (上記のコードでは$1->) は、実際のフィールドです。その結果、参照されたオブジェクトの変更はサブルーチンのスコープを超え、実際にフィールドに影響が及びます。この例題では、両方のアラートボックスに“WILLIAMS”と表示されます。

ポインタに関する詳細は、ポインタの節を参照してください。

2. メソッドDO SOMETHINGに処理を行わせるだけではなく、値を返すようにコードを書き換えることができます:

      ` MY METHODメソッド
   [People]Last Name:=DO SOMETHING ([People]Last Name) ` [People]Last Nameの値が"williams"だとします
   ALERT([People]Last Name)

      ` DO SOMETHINGメソッド
   $0:=Uppercase($1)
   ALERT($0)

サブルーチンから値が返される2番目の手法は関数と呼ばれ、次の項で説明します。

上級プログラミング: サブルーチン内の引数にはローカル変数$1, $2...を使用してアクセスできます。さらに引数を省略可能とし、${...}シンタックスを使用して参照することもできます。詳細は Count parameters関数の説明を参照してください。

関数: 値を返すプロジェクトメソッド


メソッドからデータを返すこともできます。値を返すサブルーチンを関数と呼びます。

値を返す4Dコマンドや4Dプラグインコマンドも関数と呼びます。

以下の行は、文字列のデータ長を返すLength関数を用いたステートメントです。このステートメントは、Length関数がMyLengthという変数に値を返します。

   MyLength:=Length("How did I get here?")

どのようなサブルーチンでも値を返すことができます。返す値をローカル変数$0に格納します。

例えば、Uppercase4という以下の関数は、始めの4文字を大文字に変換した文字列を返します:

   $0:=Uppercase(Substring($1; 1; 4))+Substring($1; 5)

以下は、Uppercase4 関数を使用するメソッドの例です:

   NewPhrase:=Uppercase4 ("This is good.")

変数NewPhrase には“THIS is good.”が格納されます。

戻り値 $0はサブルーチン内でローカル変数です。サブルーチンの中では$0を通常のローカル変数と同様に使用できます。例えば、前例のDO SOMETHINGにおいて、$0は最初に大文字に変換した$1の値を割り当てられ、その後ALERT コマンドの引数として使われました。サブルーチンの中では、他のローカル変数と同じ方法で$0を使うことができます。サブルーチンが終わる時の$0の値を呼び出し元のメソッドに戻すのは4Dの役割です。

プロジェクトメソッドの再帰呼び出し


プロジェクトメソッドは、自分自身を呼び出すことができます。例えば:

・メソッドAは、Aを呼び出すメソッドBを呼び出します。このためAが再びBを呼び出します。

・メソッドAは自身を呼び出すことができます。

これは再帰呼び出しと呼ばれています。4D言語は再帰呼び出しを完全にサポートしています。

例題を見てみましょう。以下のフィールドから成る[Friends and Relatives] テーブルがあります:

- [Friends and Relatives]Name

- [Friends and Relatives]ChildrensName

この例題では、フィールドの値は重複しない、すなわち同じ名前の人間はいないとします。名前を指定することで、以下のような文を作成します:“A friend of mine, John who is the child of Paul who is the child of Jane who is the child of Robert who is the child of Eleanor, does this for a living!”:

1. この文を以下のように作成できます:

   $vsName:=Request("Enter the name:";"John")
   If (OK=1)
      QUERY([Friends and Relatives];[Friends and Relatives]Name=$vsName)
      If (Records in selection([Friends and Relatives])>0)
         $vtTheWholeStory:="A friend of mine, "+$vsName
         REPEAT 
            QUERY([Friends and Relatives];[Friends and Relatives]ChildrensName=$vsName)
            $vlQueryResult:=Records in selection([Friends and Relatives])
            If ($vlQueryResult>0)
               $vtTheWholeStory:=$vtTheWholeStory+" who is the child of "+[Friends and Relatives]Name
               $vsName:=[Friends and Relatives]Name
            End if 
         Until ($vlQueryResult=0)
         $vtTheWholeStory:=$vtTheWholeStory+", does this for a living!"
         ALERT($vtTheWholeStory)
      End if 
   End if 

2. 以下の方法でも作成できます:

   $vsName:=Request("Enter the name:";"John")
   If (OK=1)
      QUERY([Friends and Relatives];[Friends and Relatives]Name=$vsName)
      If (Records in selection([Friends and Relatives])>0)
         ALERT("A friend of mine, "+Genealogy of ($vsName)+", does this for a living!")
      End if 
   End if 

再帰関数Genealogy ofは以下の通りです:

      ` Genealogy of プロジェクトメソッド
      ` Genealogy of ( String ) -> Text
      ` Genealogy of ( Name ) -> Part of sentence

   $0:=$1
   QUERY([Friends and Relatives];[Friends and Relatives]ChildrensName=$1)
   If (Records in selection([Friends and Relatives])>0)
      $0:=$0+" who is the child of "+Genealogy of ([Friends and Relatives]Name)
   End if 

Genealogy ofメソッドが自分自身を呼び出していることに注目してください。

最初に挙げた方法は反復性のアルゴリズムです。2番目に挙げた方法は再帰呼び出しのアルゴリズムです。

前述の例題のようなコードを実装する場合、反復性や再帰呼び出しを使用してメソッドを書くことができるということに注目してください。一般的に、再帰呼び出しは、より明瞭で、読みやすく、維持しやすいコードを提供します。ただし、この使用は必須ではありません。

4D内での再帰呼び出しの代表的な使用方法は以下の通りです:

・例題と同じく、お互いに関連するテーブル内でのレコードの取り扱い。

FOLDER LISTコマンドとDOCUMENT LISTコマンドを使用して、ディスク上にあるドキュメントとフォルダをブラウズする。フォルダにはフォルダとドキュメントが含まれており、サブフォルダはまたフォルダとドキュメントを含むことができます。

重要: 再帰呼び出しは、必ずある時点で終了する必要があります。例えばGenealogy ofメソッドが自身の呼び出しを止めるのは、クエリがレコードを返さないときです。この条件のテストをしないと、メソッドは際限なく自身を呼び出します。 (メソッド内で使用される引数やローカル変数と同様に) 再帰呼び出しを行う容量が一杯になると、最終的に4Dは“スタックがいっぱいです”エラーを返します 。

参照

データベースメソッド, メソッド, 制御フロー.


4D - Documentation   French   English   German   Spanish   日本語   4D v11 SQLコマンドテーマリスト   4D v11 SQLインデックス   4D v11 SQL定数テーマリスト   戻る   前   次