基本仕様 第 11 章 前の章 次の章

VB C# ALL プログラミング言語によるフィルタ (ここで選んだ言語で選別された説明や図だけが表示されます)

11. ツーピーススタイル

.NET プラットフォーム および Java プラットフォームの特徴の一つとし、ネットワークをまたにかけて活躍するプログラムにしやすい点があります。 MANDALA.net で開発するアプリケーションプログラムは、この特徴を生かして、インターネットやイントラネットなど HTTP プロトコルで通信しあう Web 対応のプログラムにすることができます。 これがスムーズに実現できるように、従来のワンピーススタイルだけでなく、ツーピーススタイルのプログラム開発向けの機能が提供されています。

ここで Web システムの発展の歴史を振り返ってみましょう。 まず発展の初期段階において、固定的な情報を閲覧するためのブラウザベースのシステムがあまりにも急速に広まったために、何もかもブラウザベースのシステムでまかなう方向に発展が進みました。 固定的でない情報を閲覧するためにもブラウザベースのシステムが使われ、さらに情報の閲覧とは趣きの異なるインプットデータの受付け処理にもブラウザベースのシステムが使われるというように、いささか無理を通して突き進んできました。 しかし、いつの日か見直しはなされるもので、ブロードバンド時代をむかえて、データインプットに即反応するレスポンシブなシステムが注目されるようになりました。いわゆるリッチクライアントシステムあるいはスマートクライアントシステムと呼ばれるものです。

こうしたシステムまでも、ブラウザベースのシステムの延長線上に構築しようとする動きもありますが、そうするのではなく、.NET プラットフォーム および Java プラットフォームの特徴を生かしたそれにふさわしい構造にした方が素直なシステムになります。 MANDALA.netツーピーススタイルのプログラムは、素直にリッチクライアントシステムに対応したものです。 特にデータインプットの多い業務アプリケーションプログラムには打ってつけのレスポンシブなシステムだといえます。


11.1 ワンピーススタイルとツーピーススタイル

ここには、ワンピーススタイルとツーピーススタイルを比べたそれぞれの特徴が書いてあります。

◇ ワンピース (ひと塊) とツーピース (ローカルピースとセントラルピース)

                 

従来のワンピーススタイルの場合は、プログラムが一つの塊となりますが、ツーピーススタイルの場合は、プログラムがローカルピース (Lcl) とセントラルピース (Cnt) の二つから構成されることになります。

注目: 同一のプログラムをワンピーススタイルにもツーピーススタイルにもすることができるので、インターネットやイントラネットを始めとする様々なシステムを構築する際に、自由度が広がり、より適切なシステム構成を選択することができます。


ワンピーススタイルでは、次のシステムを構築することができます。


ツーピーススタイルでは、次のシステムを構築することができます。


ワンピーススタイルにするのかツーピーススタイルにするのかは、そのプロジェクトに関するある指定によって決まります。 そして、ワンピースプロジェクトに対して合成の指示を与えるとワンピース向けの合成用のプログラムコードが生成されます。 同様に、ツーピースプロジェクトペアに対しては、ツーピース向けの合成用のプログラムコードが生成されます。

なお、ツーピースプロジェクトペアとは、ローカルプロジェクトとセントラルプロジェクトの二つを意味します。 すなわち、ツーピース向けの合成用のプログラムコードは、ローカルピース向けおよびセントラルピース向けの 2 種類からできあがっています。



ワンピーススタイルのシステムの例

ローカルシステムとデータベースサーバとを組み合わせた 2 階層システム


       ローカルシステム       データベースサーバ

   青色の部分:  ビジネスロジック群 (フックメソッド群)
    金色の部分:  MANDALA.net 実動フレームワーク

ビジネスロジック群は、すべてローカル側に配置され、ローカル側の MANDALA.net 実動フレームワークから呼び出されて動作します。




ツーピーススタイルのシステムの例

ローカルシステムとセントラルシステムとデータベースサーバとを組み合わせた 3 階層システム


 ローカルシステム    セントラルシステム   データベースサーバ

ローカル側フレームワーク セントラル側フレームワーク


  青色の部分:  ローカル側に配置されたビジネスロジック群
   赤色の部分:  セントラル側に配置されたビジネスロジック群
   金色の部分:  MANDALA.net 実動フレームワーク


ビジネスロジック群は、二分されてローカル側とセントラル側に配置されます。 ローカル側のビジネスロジック群は、ローカル側 MANDALA.net 実動フレームワークから呼び出されて動作し、 セントラル側のビジネスロジック群は、セントラル側 MANDALA.net 実動フレームワークから呼び出されて動作します。

ローカルシステムとセントラルシステムは、HTTP プロトコルによってデータの送受信を行います。 ただし、これはすべてローカル側とセントラル側の MANDALA.net 実動フレームワークによって行われるので、ビジネスロジックそのものはワンピーススタイルでもツーピーススタイルでも同じものでまかなうことができます。


ツーピーススタイルを採用すると、ローカル・セントラル間の通信トラフィックを最少にすることができます。従来から、ワンピーススタイルにおいてもストアードプロシージャを用いるなどして、通信トラフィックを少なくする努力がなされてきましたが、ツーピーススタイルではセントラル側にビジネスロジックの一部を配置することによって、従来よりもさらに通信トラフィックを少なくすることができます。 しかも、そのための主要ロジック (ビジネスロジック群の呼出しの制御ロジック) は、MANDALA.net が行うので、アプリケーション開発者の方々には、大きな負荷はかからないようになっています。

ここで誤解のないように付け加えておくと、ツーピーススタイルを採用しても、ローカル側で動作させるビジネスロジック群などの資源はすべてセントラル側に集中管理することができます。 したがって、ツーピーススタイルを採用するとワンピーススタイルに比べて管理の手間が大幅に軽減されます。


11.2 ツーピース用のソリューションとプロジェクト

ここには、ツーピーススタイルにするために必要なツーピース用の二つのソリューションと二つのプロジェクトについて書いてあります。


◇ プロジェクトトリオ

MANDALA.net においては、同一のプログラムをワンピーススタイルまたはツーピーススタイルのどちらの形態にもすることができます。

ツーピーススタイルの場合は、ローカル側とセントラル側にプログラムが分かれるので、それぞれにプロジェクト (すなわちローカルプロジェクトおよびセントラルプロジェクト) が必要になります。

したがって、プロジェクトとしては、ワンピースプロジェクト、およびツーピースプロジェクトペア (すなわちローカルプロジェクトおよびセントラルプロジェクト) の三つが存在し得ます。なお、これら三つのプロジェクトのことをプロジェクトトリオと呼びます。


プロジェクトを三つ作成して、プロジェクトトリオ構成しておくと、ワンピースとツーピースのどちらの形態にすることも戻すことも簡単です。すなわち、ワンピースプロジェクトに関するコード合成処理の指示を与えると、ワンピーススタイルになります。そして、ローカルプロジェクトに関するコード合成の指示を与えると、ローカルおよびセントラル両プロジェクトのコード合成処理がなされて、ツーピーススタイルになります。

ここでちょっとしたご注意ですが、ワンピーススタイルにした状態では、ローカルプロジェクトやセントラルプロジェクトをビルドするとエラーが発生してしまいます。逆も同様で、ツーピーススタイルにした状態では、ワンピースプロジェクトをビルドするとエラーが発生してしまいます。

したがって、ワンピースプロジェクトをビルドする前には、ワンピースプロジェクトに関するコード合成処理をして、ワンピーススタイルにします。同様に、ローカルプロジェクトおよびセントラルプロジェクトをビルドする前には、ローカルプロジェクトに関するコード合成の指示を与えて、ツーピーススタイルにします。


◇ ツーピーススタイル向けのソリューションとプロジェクト

ツーピーススタイルのアプリケーションを開発するには、まずツーピーススタイル用のソリューションおよびプロジェクトを作成します。つまり、ローカル用とセントラル用のそれぞれのソリューション (二つ) およびプロジェクト (二つ) が必要になります。これらを作成する手順は、以下のとおりです。


ローカル用ソリューションとセントラル用ソリューションの作成方法

これら二つのソリューションを作成するには、既存のワンピーススタイルのソリューションを統合開発環境 VS2008 で開いて、「名前を付けてソリューションを保存」 という指示を与えます。

この作成方法を詳しく述べると、ソリューションエクスプローラを開いて旧版のソリューションにフォーカスをあててから、メニュー 「ファイル(F)」 をクリックして、「名前を付けて yyyy.sln を保存(A)...」 の指示を与えてください。こうすることで、ローカル用の新たなソリューションに名前を付けることができます。名前としては、yyyyLcl.sln のように元の名前 yyyy の後に Lcl という文字を付けることをお勧めいたします。


同様の操作でセントラル用ソリューションを作成することができます。セントラル用の新たなソリューションの名前には、yyyyCnt.sln のように元の名前 yyyy の後に Cnt という文字を付けることお勧めいたします。


これらの操作によって、ワンピーススタイルのソリューション yyyy.sln から、ツーピーススタイル向けに、次の二つのソリューションを作成できます。


yyyyLcl.sln (ツーピーススタイルのローカル用ソリューション)

yyyyCnt.sln (ツーピーススタイルのセントラル用ソリューション)


ローカル用プロジェクトとセントラル用プロジェクトの作成方法

ローカル用プロジェクトを作成するには、ローカル用ソリューションを統合開発環境 VS2008 で開いてから、その中のプロジェクトに対して 「名前を付けてプロジェクトを保存」 という指示を与えます。

この作成方法を詳しく述べると、ソリューション yyyyLcl.sln をソリューションエクスプローラで表示して、その中のプロジェクト xxxx.vbproj または xxxx.csproj にフォーカスをあててから、メニュー 「ファイル(F)」 をクリックして、「名前を付けて xxxx を保存(A)...」 の指示を与えてください。このとき、ローカル用の新たなプロジェクトの名前としては、xxxxLcl.vbproj または xxxxLcl.csproj のように元の名前の後に Lcl という文字を付けたものにすることをお勧めいたします。

ここで、ちょっとした追加の作業が必要です。それは、プロジェクト xxxxLcl のプロパティページを開いて、以下のようにして条件付きコンパイル定数 (カスタム定数) の指定をすることです。こうすることで、このプロジェクトがローカル用であり、「ローカル (Local) 用またはワンピース (Op) 用のプログラムコードだけを用いることにする」という宣言になります。 なお、この指定は Debug 構成および Release 構成の両方、つまり 2 箇所に対して行ってください。

VB の場合、プロパティページの中の [構成プロパティ] - [ビルド] - [カスタム定数(S)] に以下の指定をします。

LocalOrOp = True

C# の場合、プロパティページの中の [構成プロパティ] - [ビルド] - [コード生成] - [条件付きコンパイル定数] に以下の指定をします。

LocalOrOp
 (実際には、Debug 構成の場合 DEBUG;TRACE;LocalOrOp とし、
 Release 構成の場合 TRACE;LocalOrOp とします。)


同様の操作でセントラル用プロジェクトも作成できます。セントラル用ソリューション yyyyCnt.sln を統合開発環境 VS2008 で開いて、その中のプロジェクトに対して 「名前を付けてプロジェクトを保存」 という指示を与えてください。このとき、セントラル用の新たなプロジェクトの名前には、xxxxCnt.vbproj または xxxxCnt.csproj のように元の名前の後に Cnt という文字を付けたものにすることをお勧めいたします。

それから、同様に追加の作業として、プロジェクト xxxxCnt のプロパティページを開いて、以下のようにして条件付きコンパイル定数 (カスタム定数) の指定をしてください。こうすることで、このプロジェクトがセントラル用であり、「セントラル (Central) 用またはワンピース (Op) 用のプログラムコードだけを用いることにする」という宣言になります。 なお、この指定は Debug 構成および Release 構成の両方、つまり 2 箇所に対して行ってください。

VB の場合、プロパティページの中の [構成プロパティ] - [ビルド] - [カスタム定数(S)] に以下の指定をします。

CentralOrOp = True

C# の場合、プロパティページの中の [構成プロパティ] - [ビルド] - [コード生成] - [条件付きコンパイル定数] に以下の指定をします。

CentralOrOp
 (実際には、Debug 構成の場合 DEBUG;TRACE;CentralOrOp とし、
 Release 構成の場合 TRACE;CentralOrOp とします。)


これらの操作によって、ツーピーススタイルのローカル用およびセントラル用ソリューションの中の二つのプロジェクトが次のようにそれぞれにふさわしい名前になります。


ソリューション yyyyLcl.sln の中のローカル用プロジェクトの名前が xxxxLcl.vbproj または xxxxLcl.csproj になります。

ソリューション yyyyCnt.sln の中のセントラル用プロジェクトの名前が xxxxCnt.vbproj または xxxxCnt.csproj になります。


ローカル用プロジェクトに対する追加の設定

上述のようにして作成したローカル用プロジェクトに対しては、次の二つの参照設定を行うことが必要です。

System.Runtime.Remoting

AppliTech.Remoting (または、これ相当の他社製のリモート処理 dll)


すなわち、参照設定を行うには、ローカル用ソリューションを統合開発環境 VS2008 で開いてから、その中のプロジェクトに対して 「参照の追加(R)...」 の指示を与えてください。

なお、System.Runtime.Remoting は、ダイアログ参照の追加.NET というタブの中にありますから、そこから選択してください。 また、AppliTech.Remoting は、ダイアログ参照の追加のボタン「参照(B)...」をクリックして、ファイルの場所を指定して選択してください。MANDALA.net をインストールしたフォルダの中の AppliTech.Remoting8.dll という名前の dll です。


セントラル用プロジェクトに対する追加の設定

上述のようにして作成したセントラル用プロジェクトに関しては、次の三つの追加の設定が必要です。


追加作業その 1: セントラル側にはフォームは不要ですから、セントラルプロジェクトからフォームを削除してください。あるいは、次の条件付きコンパイルディレクティブでフォームのクラス全体を括って、セントラル側では無効なクラスモジュールにしてください。

#If LocalOrOp OrElse Not CentralOrOp Then

#End If

#if( LocalOrOp || ! CentralOrOp )

#endif

追加作業その 2: このプロジェクトのプロパティページの中のアセンブリ名(N) に関する指定をローカル用プロジェクトの指定と異なるものに変えてください。


--- アセンブリ名: 各業務アプリケーションシステムごとにローカル・セントラルでそれぞれ別の (空白以外の) 名前を指定してください。なお、アセンブリ名は、exe または dll の名前として使われるので、ユニークな名前にしなければなりません。---

--- ルート名前空間または規定の名前空間: 各業務アプリケーションシステムごとにローカル・セントラルとも同じ (空白以外の) 名前を指定してください。なお、ルート名前空間は、業務アプリケーションシステムごとに、ユニークな名前にすることをお勧めいたします。---

--- ルート名前空間または規定の名前空間が、xxxx ならば、ローカルピースのアセンブリ名は、xxxxLcl として、セントラルピースのアセンブリ名は、xxxxCnt とするのが分かりやすいでしょう。なお、ワンピースのアセンブリ名は、xxxx とすることをお勧めいたします。---


追加作業その 3: このプロジェクトのプロパティページの中の出力の種類(O) に関する指定をクラスライブラリにしてください。 すなわち、セントラルプロジェクトは exe ではなく dll という形態にして、これ一つでローカル側からの複数の処理要求に同時に対応できるようにします。


ツーピース用のソリューションへの補助的プロジェクトの追加

ここには、起動の役割を果たす補助的プロジェクト CentralMain およびローカル・セントラル間の通信に関係する補助的プロジェクト ca を追加する作業について書いてあります。


セントラルプロジェクトは dll という形態になるので、これを起動するプログラムがセントラル側に必要になります。 ですから、セントラルソリューションに起動の役割を果たす補助的プロジェクト CentralMain を組み込んでください。

補助的プロジェクト CentralMain は、たとえばサンプルアプリのプロジェクト \Vb\Jutyu2\Jutyu2Cnt.vbproj または \Cs\Jutyu2\Jutyu2Cnt.csproj に含まれていますから、このプロジェクトをセントラルプロジェクトのフォルダにコピーして、セントラルソリューションに追加してください。

このようにすると、セントラルソリューションには少なくとも二つのプロジェクトが含まれることになるので、どれをスタートアッププロジェクトにするのかという設定が必要になります。 そこで、補助的プロジェクト CentralMain をスタートアッププロジェクトにするために、VS2008 のソリューションエクスプローラの中のプロジェクト CentralMain をマウスで右クリックで現れるポップアップメニューの中のスタートアッププロジェクトに設定(A) をクリックしてください。


ツーピーススタイルの場合、MANDALA.net はローカル・セントラル間でいろいろな情報の通信を行います。この通信の一部には、特別のプロジェクトを必要とするものがあります。 それは、後述の Common を用いた場合になされる通信、および後述の RHMI を用いた場合になされるオブジェクト通信です。 このような機能 (どちらか一方または両方) を用いる場合には、ca プロジェクトと呼ばれるプロジェクトをローカルソリューションおよびセントラルソリューションの両方に追加することが必要になります。

正確に述べると、ローカル・セントラル間に分散配置される変数の値を一致させるために Common を用いる場合には、ca プロジェクトを作成して (これは空のプロジェクトでかまわない)、これをローカルソリューションおよびセントラルソリューションの両方に追加してください。 そして、ダイアログプロジェクトオプションca プロジェクト欄に ca プロジェクトのフルパスファイル名を設定してください。 こうしておくと、コード合成時に ca プロジェクトに生成モジュールが組み込まれます。 なお、ca プロジェクトは、ローカルプロジェクトおよびセントラルプロジェクトから参照できるように、これらのプロジェクトに参照設定を行ってください。

また、RHMI を用いてローカル・セントラル間のオブジェクト通信を行うには、オブジェクトを Serializable 属性のクラスとして宣言しておくことが必要です。 そして、ダイアログプロジェクトオプションca プロジェクト欄に ca プロジェクトのフルパスファイル名を設定してください。 そして、このクラスモジュールを ca プロジェクトの中に含めておいてください。 なお、ca プロジェクトは、ローカルプロジェクトおよびセントラルプロジェクトから参照できるように、これらのプロジェクトに参照設定を行うことが必要です。


ワンピーススタイル向けのプロジェクトの補正

ここで、ワンピーススタイル向けのプロジェクト xxxx.vbproj または xxxx.csproj の条件付きコンパイル定数 (カスタム定数) の補正をしておくことをお勧めいたします。この補正によって、ツーピーススタイルに分割した後でも、元のワンピーススタイルの業務プログラムを合成することが可能になります。

補正の方法は、ワンピーススタイル向けのプロジェクト xxxx のプロパティページを開いて、以下のようにして条件付きコンパイル定数 (カスタム定数) の指定をしてください。こうすることで、このプロジェクトがワンピース用であり、「ローカル用とセントラル用の両方を含めたワンピース用のプログラムコードを用いることにする」という宣言になります。 なお、この指定は Debug 構成および Release 構成の両方、つまり 2 箇所に対して行ってください。

VB の場合、プロパティページの中の [構成プロパティ] - [ビルド] - [カスタム定数(S)] に以下の指定をします。

LocalOrOp = True : CentralOrOp = True

C# の場合、プロパティページの中の [構成プロパティ] - [ビルド] - [コード生成] - [条件付きコンパイル定数] に以下の指定をします。

LocalOrOp;CentralOrOp
 (実際には、Debug 構成の場合 DEBUG;TRACE;LocalOrOp;CentralOrOp とし、
 Release 構成の場合 TRACE;LocalOrOp;CentralOrOp とします。)


--- 正確に述べると、ワンピーススタイル向けのプロジェクトのプロパティページの条件付きコンパイル定数 (カスタム定数) の指定は必ずしも必要ありません。 なぜなら、各フッククラスの条件付きコンパイルディレクティブの記述が以下のようになっているはずなので、条件付きコンパイル定数 (カスタム定数) が何も指定されない場合には、すべてのプログラムコードがコンパイルされる状況 (つまりワンピース向け) になるからです。---


    ・・・

#If LocalOrOp OrElse Not CentralOrOp Then
    ・・・
#End If

#If CentralOrOp OrElse Not LocalOrOp Then
    ・・・
#End If



    ・・・

#if( LocalOrOp || ! CentralOrOp )
    ・・・
#endif

#if( CentralOrOp || ! LocalOrOp )
    ・・・
#endif


--- 必ずしも必要ないのですが、ワンピーススタイル向けのプロジェクトのプロパティページの条件付きコンパイル定数 (カスタム定数) を上述のように指定することをお勧めいたします。 なぜなら、各フッククラスの条件付きコンパイルディレクティブの記述が簡略化されて以下のようになっていても、すべてのプログラムコードがコンパイルされる状況 (つまりワンピース向け) になるからです。---


    ・・・

#If LocalOrOp Then
    ・・・
#End If

#If CentralOrOp Then
    ・・・
#End If



    ・・・

#if( LocalOrOp )
    ・・・
#endif

#if( CentralOrOp )
    ・・・
#endif


11.3 ビジネスロジックなどの配置

ここには、ビジネスロジックなどのプログラムコードをローカル側とセントラル側に分けて配置する方法について書いてあります。

◇ ビジネスロジックの配置

MANDALA.net を用いた開発においては、ビジネスロジックはフッククラスの中にいくつかのフックメソッドとして記述されます。 そして、各フックメソッドをローカル側またはセントラル側に分散配置することによって、ツーピーススタイルのプログラムにすることができます。

--- ここで、ブラウザベースのシステムと比較してみましょう。 ブラウザベースのシステムではローカル側のビジネスロジックは Java スクリプト (Java とは異なる言語) などの特殊なスクリプト言語で記述し、セントラル側のビジネスロジックは Java で記述するなど統一がとれていません。 MANDALA.net を用いたシステムでは、Visual Basic または Visual C# などの一つの言語でローカル・セントラル双方のビジネスロジックを記述できますし、ワンピーススタイルでもツーピーススタイルでも同じビジネスロジックでまかなうことができます。---

ビジネスロジックはフックメソッドとして記述されますが、フックメソッドの種類によってその性格が異なるので、ローカル側で動作させるものやセントラル側で動作させるものなど配置する上での配慮が必要です。 たとえば、ユーザインタフェースに関係するフックメソッドは大抵の場合ローカル側で動作させるべきでしょうし、セントラル側のデータベースへのアクセスが必要なフックメソッドはセントラル側で動作させる方がよいでしょう。

そこで、各フックメソッドは、どこに配置すべきかという属性によって次の四つに分類されています。


つまり、各フックメソッドをどこに配置することができるのかという仕様は、以下のようになっています。


ローカル側に配置するフックメソッド

項目フックメソッド BeginPrgCloseFuriganaKeyPreviewLocalOpenNextCtrlResponseSetDerivedSkipSList はローカル側に配置します。

画面フックメソッド ActivatedBeginPrgCloseDerivedErrorMsgEScrollKeyPreviewLocalOpenPageDownPageUpRequestReceiveScrollUpdateNow はローカル側に配置します。

これらのフックメソッドは、セントラル側に配置することはできません。

言うまでもないことですが、これらのフックメソッドが必要ないときには、どこにも配置しません。


セントラル側に配置するフックメソッド

項目フックメソッド BeginPrgALclCentralCheckCheckCCheckRCloseBLclDerivedDerivedCDerivedRInitValOpenALcl はセントラル側に配置します。

画面フックメソッド BeginPrgALclCentralCloseBLclOpenALclReceiveResponseRelCheck はセントラル側に配置します。

これらのフックメソッドは、ツーピーススタイルにおいては、ローカル側に配置することが禁止されています。

なお、ワンピーススタイルにおいては、セントラル側というものが存在せず、ローカル側だけなので、フックメソッドの配置に関するこの規則は意味がありません。

言うまでもないことですが、これらのフックメソッドが必要ないときには、どこにも配置しません。


どちらかに配置できるフックメソッド (どちらか一方に配置するか、どちらにも配置しない)

項目フックメソッド GetEventHelpInitMasterPromptRelInfTermUnprompt はローカル側かセントラル側のどちらか一方に配置できます。

画面フックメソッド AppendAppendChkCurrentDeleteDeleteDREachItemFirstGetEventIndicateIndicateExecInitLastNextFhPrevSelectFhSelectExecTermUpdateUpdateChkVisibleChanged はローカル側かセントラル側のどちらか一方に配置できます。

これらのフックメソッドは、ツーピーススタイルにおいては、ローカル側およびセントラル側の双方に同種のものを配置することが禁止されています。

なお、ワンピーススタイルにおいては、セントラル側というものが存在せず、ローカル側だけなので、フックメソッドの配置に関するこの規則は意味がありません。

言うまでもないことですが、これらのフックメソッドが必要ないときには、どこにも配置しません。


双方に同一のものを配置するフックメソッド

項目フックメソッド CheckLCCheckCLCCheckRLCDerivedLCDerivedCLCDerivedRLCInitValLC はローカル側およびセントラル側の双方に同一のものを配置します。

画面フックメソッド RelCheckLC はローカル側およびセントラル側の双方に同一のものを配置します。

これらのフックメソッドは、ローカル側またはセントラル側のどちらか一方だけに配置することは禁止であり、双方に同一のものを配置しなければなりません。

なぜなら、双方に同一のものを配置されていることを前提にして、MANDALA.net 実動フレームワークにとって都合のよい方に配置されているものが呼び出され使われることになるからです。ですから、もしもローカル側およびセントラル側に配置されたフックメソッドの内容が異なる場合には、動作に異常をきたすことになりかねません。

なお、ワンピーススタイルにおいては、セントラル側というものが存在せず、ローカル側だけなので、フックメソッドの配置に関するこの規則は意味がありません。

言うまでもないことですが、これらのフックメソッドが必要ないときには、どこにも配置しません。


◇ ツーピーススタイル向けに各フックメソッドを配置する作業

フッククラスの中の各フックメソッドは、それぞれローカル側、またはセントラル側どちらか一方双方に配置できるのか決まっています。 そこで、これに違反しないふさわしい領域にフックメソッドを再配置してください。領域は 3 種類あり、それぞれの領域がどこに配置されるのかは条件付きコンパイルディレクティブによって指定されます。

なお、ワンピーススタイルの場合には、この配置作業は必要ありませんが、たとえばワンピーススタイルのプログラムをツーピーススタイルとしても使えるように格上げするには、ここに述べる配置の作業が必要になります。


' VB 版のフッククラスの場合
Friend Class クラス名

#Region "ローカルピース、 セントラルピース共通に用いるフックメソッドなど"
    ' ここに「双方に同一のものを配置するフックメソッド」を配置する
#End Region ' ローカルピース、 セントラルピース共通に用いるフックメソッドなど

#Region "ローカルピースに配置するフックメソッドなど"
#If LocalOrOp OrElse Not CentralOrOp Then
    ' ここに「ローカル側に配置するフックメソッド」および
    '「どちらかに配置できるフックメソッド」のうちローカル側とするものを配置する
#End If
#End Region ' ローカルピースに配置するフックメソッドなど

#Region "セントラルピースに配置するフックメソッドなど"
#If CentralOrOp OrElse Not LocalOrOp Then
    ' ここに「セントラル側に配置するフックメソッド」および
    '「どちらかに配置できるフックメソッド」のうちセントラル側とするものを配置する
#End If
#End Region ' セントラルピースに配置するフックメソッドなど

End Class
// C# 版のフッククラスの場合
internal class クラス名 {

    #region ローカルピース、 セントラルピース共通に用いるフックメソッドなど
    // ここに「双方に同一のものを配置するフックメソッド」を配置する
    #endregion ローカルピース、 セントラルピース共通に用いるフックメソッドなど

    #region ローカルピースに配置するフックメソッドなど
#if( LocalOrOp || ! CentralOrOp )
    // ここに「ローカル側に配置するフックメソッド」および
    //「どちらかに配置できるフックメソッド」のうちローカル側とするものを配置する
#endif
    #endregion ローカルピースに配置するフックメソッドなど

    #region セントラルピースに配置するフックメソッドなど
#if( CentralOrOp || ! LocalOrOp )
    // ここに「セントラル側に配置するフックメソッド」および
    //「どちらかに配置できるフックメソッド」のうちセントラル側とするものを配置する
#endif
    #endregion セントラルピースに配置するフックメソッドなど

}

上記のように、Region ディレクティブによって各クラスに次の三つの領域を設けます。

一つ目の領域 [共] には、条件付きコンパイルディレクティブの指定をしません。 したがって、無条件に (ローカル側もセントラル側も) コンパイルされることになります。

ここで二つ目の領域 [ロ] には、 ローカル (Local) 用またはワンピース (Op) 用のプログラムコードだけがコンパイルされるような条件付きコンパイルディレクティブの指定をします。

同様に三つ目の領域 [セ] には、 セントラル (Central) 用またはワンピース (Op) 用のプログラムコードだけがコンパイルされるような条件付きコンパイルディレクティブの指定をします。

こうしておいてから、プログラムコードをこの三つの領域のうちのどこか一つに再配置します。


詳しくは、以下のように二つのステップで、フックメソッドの配置を行います。

第一ステップでは、各フックメソッドを次の 3 種類に分類してください。

[共] ローカルピース、 セントラルピース共通に用いたいフックメソッド

  「双方に同一のものを配置するフックメソッド」

[ロ] ローカル側に配置したいフックメソッド

  「ローカル側に配置するフックメソッド」および

  「どちらかに配置できるフックメソッド」のうちローカル側とするもの

[セ] セントラル側に配置したいフックメソッド

  「セントラル側に配置するフックメソッド」および

  「どちらかに配置できるフックメソッド」のうちセントラル側とするもの


第二ステップでは、以下の Region 文および条件付きコンパイルディレクティブをコピーアンドペーストで各クラスモジュールに貼り付けてください。 そして、上記で分類した各メソッドを 印の相応しいところに移動してください。移動はカットアンドペーストで行えばよいでしょう。


各クラスに貼り付けるべき Region 文および条件付きコンパイルディレクティブ

VB の場合

#Region "ローカルピース、 セントラルピース共通に用いるフックメソッドなど"
    '  ここに [共] をカットアンドペーストで移動する
#End Region ' ローカルピース、 セントラルピース共通に用いるフックメソッドなど

#Region "ローカルピースに配置するフックメソッドなど"
#If LocalOrOp OrElse Not CentralOrOp Then
    '  ここに [ロ] をカットアンドペーストで移動する
#End If
#End Region ' ローカルピースに配置するフックメソッドなど

#Region "セントラルピースに配置するフックメソッドなど"
#If CentralOrOp OrElse Not LocalOrOp Then
    '  ここに [セ] をカットアンドペーストで移動する
#End If
#End Region ' セントラルピースに配置するフックメソッドなど

C# の場合

    #region ローカルピース、 セントラルピース共通に用いるフックメソッドなど
    //  ここに [共] をカットアンドペーストで移動する
    #endregion ローカルピース、 セントラルピース共通に用いるフックメソッドなど

    #region ローカルピースに配置するフックメソッドなど
#if( LocalOrOp || ! CentralOrOp )
    //  ここに [ロ] をカットアンドペーストで移動する
#endif
    #endregion ローカルピースに配置するフックメソッドなど

    #region セントラルピースに配置するフックメソッドなど
#if( CentralOrOp || ! LocalOrOp )
    //  ここに [セ] をカットアンドペーストで移動する
#endif
    #endregion セントラルピースに配置するフックメソッドなど

上述の配置方法は、フックメソッドに関するものとして説明してきましたが、フックメソッドだけでなく、その他のメソッドおよびプロパティについても同様に三つの領域 ([共][ロ][セ]) に再配置してください。

このように配置することによって、ローカル用のプロジェクトではローカル用のプログラムコードだけがコンパイルされ、セントラル用のプロジェクトではセントラル用のプログラムコードだけがコンパイルされるようになります。


◇ ローカル・セントラル共通変数の配置

ここまでの作業によって、フックメソッド、その他のメソッド、およびプロパティを三つの領域 ([共][ロ][セ]) に分けて配置できますが、 同様に変数についても、三つの領域に分けて再配置してください。 なお、この作業においては、できるだけ [ロ] または [セ] に配置するようにして、[共] の領域に配置する変数は最少になるようにしてください。

ところで、[共] 向けの領域に配置した変数 (共用変数) に関しては、ローカル側とセントラル側の両方に別々に配置されることになるので、その値が常に一致しているという保証がなくなってしまいます。 しかるに、ワンピーススタイルの場合には、この変数は 1 箇所に配置されるだけなので、二つの値をとることはなく、ある一つの値をとるものとしてプログラミングがなされています。 一つの値をとるはずの変数が、ローカル側とセントラル側に分かれて別々の値をとるということは、大きな問題です。

この問題を解決するためには、ローカル側とセントラル側の両方に別々に配置された (元来は一つであった) 変数の値を一致させる処理 (コヒーレント制御) が欲しくなります。 コヒーレント制御がなされれば、ワンピーススタイルでもツーピーススタイルでも、同じプログラムコードでまかなうことができるようになるからです。

MANDALA.net では、ツーピーススタイルのサポート機能の一つとして、このコヒーレント制御を自動的に行うようになっています。 ただし、これを利用するためには、少しばかりプログラムの書換えが必要になります。


このプログラムの書換え作業は、以下に述べるようにかなり機械的に行えます。

第一に、Common という名前のインタフェースを設けて、変数の宣言をプロパティの宣言に書き換えます。

なお、以下の例は変数宣言の修飾子が Friend または internal になっていますが、Private または private であっても、書換え結果に修飾子は現れないので、目指す書換え結果のコードは変わりありません。

VB の場合

Friend Class cccc

    Friend 有効日付 As DateTime
    Friend 追加モードに移行直後 As Boolean

    ・・・

End Class ' cccc

上記のような変数宣言を、下記のようなインタフェース Common の中のプロパティ宣言に書き換えます。

Friend Class cccc

    Friend Interface Common
        Property 有効日付() As DateTime
        Property 追加モードに移行直後() As Boolean
    End Interface ' Common

    ・・・

End Class ' cccc

C# の場合

internal class cccc {

    internal DateTime 有効日付;
    internal bool 追加モードに移行直後;

    ・・・

} // cccc

上記のような変数宣言を、下記のようなインタフェース Common の中のプロパティ宣言に書き換えます。

internal class cccc {
    internal interface Common {
        DateTime 有効日付
        { get; set; }
        bool 追加モードに移行直後
        { get; set; }
     } // Common

    ・・・

} // cccc

第二に、Common のインスタンス co を必要に応じて求めて、プログラムコードの中に現れる変数名 (変数宣言以外のところ) を以下のように co.変数名 に書き換えます。


VB の場合

Friend Class cccc

    ・・・

    Friend Function 実行開始処理(ByVal fB As FormBase) As Boolean
        有効日付 = 有効日付定数

        ・・・

    End Function ' 実行開始処理

    Friend Function 初期値双方(ByVal fB As FormBase, ByVal 受注日付 As String, ByVal 詳_受注日付 As ItemBase) As String
        If 追加モードに移行直後 Then
            Return ・・・
        Else
            Return ・・・
        End If
    End Function ' 初期値双方

End Class ' cccc

上記のような変数の参照箇所 (太文字の部分) を、下記のように書き換えます。

Friend Class cccc

    ・・・

    Friend Function 実行開始処理(ByVal fB As FormBase) As Boolean
        Dim co As Common = CType(fB.getCommon(), Common)
        co.有効日付 = 有効日付定数

        ・・・

    End Function ' 実行開始処理

    Friend Function 初期値双方(ByVal fB As FormBase, ByVal 受注日付 As String, ByVal 詳_受注日付 As ItemBase) As String
        Dim co As Common = CType(fB.getCommon(), Common)
        If co.追加モードに移行直後 Then
            Return ・・・
        Else
            Return ・・・
        End If
    End Function ' 初期値双方

End Class ' cccc

C# の場合

internal class cccc {

    ・・・

    internal bool 実行開始処理( FormBase fB ) {
        有効日付 = 有効日付定数;

        ・・・

    } // 実行開始処理

    internal string 初期値双方( FormBase fB, string 受注日付, ItemBase 詳_受注日付 ) {
        if( 追加モードに移行直後 ) {
            return ・・・;
        }
        else {
            return ・・・;
        }
    } // 初期値双方

} // cccc

上記のような変数の参照箇所 (太文字の部分) を、下記のように書き換えます。

internal class cccc {

    ・・・

    internal bool 実行開始処理( FormBase fB ) {
        Common co = (Common) fB.getCommon();
        co.有効日付 = 有効日付定数;

        ・・・

    } // 実行開始処理

    internal string 初期値双方( FormBase fB, string 受注日付, ItemBase 詳_受注日付 ) {
        Common co = (Common) fB.getCommon();
        if( co.追加モードに移行直後 ) {
            return ・・・;
        }
        else {
            return ・・・;
        }
    } // 初期値双方

} // cccc

ローカル・セントラル共通変数に関するプログラムコードを上述のように書き換えて、MANDALA.net のコード合成を行い、後述のように生成される CoherentArea を ca プロジェクトに含めることによって、コヒーレント制御が自動的になされるようになります。 つまり、ワンピーススタイルの場合もツーピーススタイルの場合も、同じプログラムコードでまかなうことができるようになります。


◇ CoherentArea と ca プロジェクト

インタフェース Common を用いているプロジェクトに対して MANDALA.net のコード合成を行うと、以下のクラスモジュールが生成されます。


個別 Common は、コード合成対象のプロジェクトごとに生成されるクラスモジュールで、インタフェース Common を定義する役割を果たします。これはコード合成の際にプロジェクトに組み込まれます。そのファイル名は xxxxCommon.vb または xxxxCommon.cs という形をしています。

個別 CoherentArea は、コード合成対象のプロジェクトごとに生成される Serializable 属性のクラスモジュールで、コヒーレント制御に必要な Serialize および DeSerialize 処理を行うものです。これはコード合成の際に ca プロジェクトと呼ばれる特殊なプロジェクトに組み込まれます。そのファイル名は zzzzCoherentArea.vb または xxxxCoherentArea.cs という形をしています。

MANDALA.net コード合成ツールは、ほとんどの作業を自動的に行いますが、ca プロジェクトに関してはコード合成の前に手作業で用意しておくことが必要です。 そして、ダイアログプロジェクトオプションca プロジェクト欄に ca プロジェクトのフルパスファイル名を設定しておいてください。


11.4 ツーピーススタイルのための支援

一般に、ツーピーススタイルのプログラムは、ワンピーススタイルの場合に比べて開発が難しいものです。そこで、いろいろなご支援をすることで、ワンピーススタイルのプログラムと同様に容易に開発できるようにすることを目指しました。目標としては、生成時のエラーとコンパイルエラーをなくせば、それなりに動作するプログラムができ上がることとしました。

特に、既存のワンピーススタイルのプログラムは、すでにデバッグがなされているわけですから、生成時のエラーとコンパイルエラーをなくせば、ほぼ完成となることを目標にしました。


こうした目標が実現できるように、次のご支援を行っています。

・ フックメソッドのローカル・セントラル分割の支援
     生成時のエラーメッセージにより分割作業をご支援

・ ローカル・セントラル間に分散配置される変数に関する支援
     インタフェース Common のサポート

・ 生成時・コンパイル時のサイトアフィニティ問題の早期検出
     生成時のエラーメッセージ、および
     実行時ではなくコンパイル時にエラーとする仕組み


なお、以上の支援をしても、デバッグやテストが全く不要になるわけではありません。そこで、次のご支援を行うことで、デバッグ作業を容易にできるようにしました。


◇ ローカル・セントラル間における変数値の伝播

ツーピーススタイルのプログラムにおいては、ローカル側で変更した変数をセントラル側で参照したいこともあるでしょうし、その逆もあることでしょう。 そこで、ローカル・セントラル間で変数の値を一致させるコヒーレント制御が求められることになります。 コヒーレント制御をどう行うか (コヒーレント対象の特定、値を一致させるタイミング、プログラミング方法) は、通信の情報量や頻度などの性能に大いに関係しますし、アプリケーション開発の生産性にも関係します。 そこで、次の三つのコヒーレント制御のサービスをご提供することにしましたので、この中から適切なものを選択することができます。


バーチャル項目

一般に、MANDALA コントロールの値は、自動的にコヒーレント制御がなされるようになっているので、ローカル・セントラル間で不整合が生じることはありません。このことは、バーチャル項目についても同様です。 したがって、変数をバーチャル項目にすれば、コヒーレント制御のサービスを受けることができます。ただし、バーチャルオブジェクトについては特別の指定をしないとコヒーレント制御がなされません。

バーチャル項目を用いると、変更があった項目の値だけがローカル・セントラル間でやりとりされるので効率的です。ただし、バーチャル項目にするためには、少しばかりのプログラムの書換えが必要になります。そして、バーチャルオブジェクトは例外ですが、扱える変数の型が基本的なものに限られています。


注意事項: バーチャル項目の場合は問題ないのですが、MANDALA.net コントロールの値 (Text プロパティ) を直接に変更するようなプログラムがあると、その変更はローカル・セントラル間で伝播されないので不整合が生じます。 したがって、MANDALA.net コントロールの値 (Text プロパティ) を直接に変更するのではなく、setValue などのメソッドによって変更するようにしてください。


ローカル・セントラル間の共通域 Common

変数をバーチャル項目にしなくても、その変数をローカル・セントラル共通のインタフェース Common の中にプロパティとして宣言することによっても、コヒーレント制御のサービスを受けることができます。

この方法を用いると、自動的にローカル・セントラル間で変更データがやりとりされるので便利です。 また、プログラムの書換えもごく微量ですみますし、大抵の場合は変更があった項目の値だけがローカル・セントラル間でやりとりされるので効率的です。

ただし、効率的なのは、最適化のためのプロジェクトオプション「ca 転送量最少化」がオンで、変数 (プロパティ) の型が文字列、日付、真偽値、十進数、長整数、整数、短整数、バイトの場合に限られます。 これ以外の型か配列がある場合には、「ca 転送量最少化」をオンにすることは禁止であり、通信のたびに毎回ローカル・セントラル間でデータがやりとりされることになります。


RHMI (Remote Hook Method Invocation) による変数値のやりとり

バーチャル項目や共通域 Common は、ローカル・セントラル間で自動的に変数値のやりとりがなされますが、RHMI を用いることで、これを手動で行うことができます。 この場合、どれを対象にしてどのタイミングでコヒーレント制御を行うかは、自由に選べるので、性能への細かな配慮をすることができます。しかし、その分だけプログラミングが面倒になります。


三つの方法の比較評価

以上の三つの方法を比較評価すると、以下のようになります。

バーチャル項目

共通域 Common

RHMI


このことから、単純な型のデータの場合には、バーチャル項目または共通域 Common を用いればよいといえます。 そして、オブジェクト型の場合には、プログラミングのしやすさと性能とのトレードオフで、共通域 Common または RHMI を選択すればよいでしょう。

◇ Common の詳細

共通域 Common の中の変数については、ローカル・セントラル間で変数の値が不一致にならないようにデータのやりとりが自動的になされます。ですから、その参照はどちらのサイトからも簡単に (他のサイトを参照することなく) 行えるようになっています。

また、共通域 Common の中の変数は、画面フックメソッドからも項目フックメソッドからも参照できます。さらに、複数の画面をもつプロジェクトにおいてはそれぞれの画面フックメソッドからも参照できます。

共通域 Common は、いわば、ソリューション内で共通に参照できる領域であり、この共通域をローカル・セントラル間でコヒーレント制御がなされるように拡張したものだといえます。


共通域 Common の変数は、それぞれの画面フッククラス、または項目フッククラスの Interface 宣言の中に次のように Property として宣言します。

Interface の名前は Common と決められています。Interface ステートメントは、Class ステートメントの後 (直後あたりがお勧め) に、Friend Interface として記述してください。通常、変数は Dim として宣言しますが、共通域 Common の変数は、Property として宣言するのだと捉えてください。Property として宣言した変数には、初期値を指定できませんが、これは VB 6.0 の変数宣言に初期値を指定できなかったのと同じですから、大きな問題にはならないでしょう。


Friend Class 受注業務

   Inherits AppliFrame.複合モード画面親部品

   ・・・

   Friend Interface Common

       Property Test() As Integer

       Property 追加モード非直後() As Boolean

       Property 手動カーソル移動() As Boolean

       Property 受注コード選択リスト() As Dlg_受注コード

       Property 受注ファイル() As 受注ファイルアクセス

       Property 発注元ファイル() As 発注元ファイルアクセス

       Property 商品ファイル() As 商品ファイルアクセス

   End Interface 'Common

   ・・・


共通域 Common の変数を参照するには、次のようにオブジェクト変数 co を定義して、co で修飾して参照します。


   Dim co As Common = CType(fB.getCommon(), Common)


   co.追加モード非直後 = True


   co.受注ファイル = New 受注ファイルアクセス(fB.MyBinPath + "JutyuCd.fil", 1, 6)



Common をうまく活用するためのヒント

オブジェクト変数 co をモジュールレベルの変数として定義して、co の値を BeginPrg および BeginPrgALcl で設定するようにすれば、共通域 Common の変数の前に co. を付けるだけのプログラムの書換えで済むようになります。ただし、以下で述べる注意が必要です。


   Private fB As FormBase 'FormBase のインスタンス

   Private fH As SSSMAIN '画面フッククラス のインスタンス

   Private co As Common 'Common のインスタンス


   Friend Function BeginPrg(ByVal fB As FormBase) As Boolean

       Me.fB = fB

       Me.fH = CType(fB.myFormHook, SSSMAIN)

       Me.co = CType(fB.getCommon(), Common)

       ・・・()

   End Function


       co.追加モード非直後 = True


      co.受注ファイル = New 受注ファイルアクセス(fB.MyBinPath + "JutyuCd.fil", 1, 6)


なお、ここで述べてきたアクセス方式には Common という Interface の宣言 (上述の Friend Interface Common という宣言) だけでなく、Interface を実装したクラスが必要になりますが、この実装クラスについては MANDALA.net が生成するので、これを手組みしたり手修正したりする必要はありません。


◇ RHMI (Remote Hook Method Invocation)

RHMI は、リモートプロシージャコールおよび RMI (リモートメソッドインボケーション) などの技術を MANDALA.net の項目指向のフックメソッド体系と相性のよい形にしたものです。項目指向のフックメソッド体系にすることで、MANDALA.net の特徴である再利用性の高いフッククラスの構成要素になっています。

RHMI によって、次の三つの機能を果たすことができます。

RHMI には、方向の違いによって、ローカルピースから起動するものと、セントラルピースから起動するものの 2 種類があります。


ローカルピースから起動する RHMI (invokeCentral)

ローカル側のメソッド invokeCentral を用いると、セントラル側のフックメソッド Central を呼び出すことができます。なお、これはワンピースの場合でも機能します。

invokeCentral には、FormBase のメソッドと ItemBase のメソッドがあり、それぞれ画面フックメソッド Central および項目フックメソッド Central を呼び出すことができます。


FormBase のメソッド invokeCentral は、FormBase のインスタンス fB で修飾して fB.invokeCentral のようにして、次のようにして使います。


    Dim 受領オブジェクト As Records.JutyuCd = CType(fB.invokeCentral(送付オブジェクト), Records.JutyuCd)
    Records.JutyuCd 受領オブジェクト = (Records.JutyuCd) fB.invokeCentral(送付オブジェクト);

同様に、ItemBase のメソッド invokeCentral は、たとえば ItemBase のインスタンス iB_商品コード で修飾して iB_商品コード.invokeCentral のようにして、次のようにして使います。


    Dim 受領オブジェクト As Records.SyohinCd = CType(iB_商品コード.invokeCentral(送付オブジェクト), Records.SyohinCd)
    Records.SyohinCd 受領オブジェクト = (Records.SyohinCd) iB_商品コード.invokeCentral(送付オブジェクト);

これらの例では、セントラルから受信するオブジェクト (受領オブジェクト) の型は、それぞれ Records.JutyuCd および Records.SyohinCd になっています。 一般に受領オブジェクトは、上記の例のようにその型でキャストすることが必要です。

送付オブジェクトおよび受領オブジェクトとしては、.NET で定義された整数型 (Integer, int)、真偽値型 (Boolean, bool)、文字列型 (String, string) などの Serializable 属性をもつ既定義の型を使うことができますし、下記のように Serializable 属性の指定をした Public Class として定義したクラスを使うこともできます。 後者の場合、そのクラスは両方のソリューションから共通に参照できるアセンブリに含めて、ローカルプロジェクトおよびセントラルプロジェクトから参照設定することが必要です。 したがって、これらを定義したクラスモジュールは、ca プロジェクトに含めることをお勧めいたします。


    <Serializable()> Public Class JutyuCd ' ★ <Serializable()> の指定が必要。
        ・・・
    End Class
    <Serializable()> Public Class SyohinCd ' ★ <Serializable()> の指定が必要。
        ・・・
    End Class
    [Serializable()] public class JutyuCd { // ★ [Serializable()] の指定が必要。
        ・・・
    }
    [Serializable()] public class SyohinCd { // ★ [Serializable()] の指定が必要。
        ・・・
    }

invokeCentral は、Local および Central フックメソッドの中では使えません。


フックメソッド Central の中では、invokeLocal および invokeCentral を呼び出すことはできません。


セントラルピースから起動する RHMI (invokeLocal)

プロジェクトオプションセントラル側主導機能 (複スレッドモード) をオンにしておくと、セントラル側のメソッド invokeLocal を用いて、ローカル側のフックメソッド Local を呼び出すことができます。なお、これはワンピースの場合でも機能します。

invokeLocal には、FormBase のメソッドと ItemBase のメソッドがあり、それぞれ画面フックメソッド Local および項目フックメソッド Local を呼び出すことができます。


FormBase のメソッド invokeLocal は、FormBase のインスタンス fB で修飾して fB.invokeLocal のようにして、次のようにして使います。


    Dim 受領オブジェクト As Records.JutyuCd = CType(fB.invokeLocal(送付オブジェクト), Records.JutyuCd)
    Records.JutyuCd 受領オブジェクト = (Records.JutyuCd) fB.invokeLocal(送付オブジェクト);

同様に、ItemBase のメソッド invokeLocal は、たとえば ItemBase のインスタンス iB_商品コード で修飾して iB_商品コード.invokeLocal のようにして、次のようにして使います。


    Dim 受領オブジェクト As Records.SyohinCd = CType(iB_商品コード.invokeLocal(送付オブジェクト), Records.SyohinCd)
    Records.SyohinCd 受領オブジェクト = (Records.SyohinCd) iB_商品コード.invokeLocal(送付オブジェクト);

これらの例では、ローカルから受信するオブジェクト (受領オブジェクト) の型は、それぞれ Records.JutyuCd および Records.SyohinCd になっています。 一般に受領オブジェクトは、上記の例のようにその型でキャストすることが必要です。

送付オブジェクトおよび受領オブジェクトとしては、.NET で定義された整数型 (Integer, int)、真偽値型 (Boolean, bool)、文字列型 (String, string) などの Serializable 属性をもつ既定義の型を使うことができますし、下記のように Serializable 属性の指定をした Public Class として定義したクラスを使うこともできます。 後者の場合、そのクラスは両方のソリューションから共通に参照できるアセンブリに含めて、ローカルプロジェクトおよびセントラルプロジェクトから参照設定することが必要です。 したがって、これらを定義したクラスモジュールは、ca プロジェクトに含めることをお勧めいたします。


    <Serializable()> Public Class JutyuCd ' ★ <Serializable()> の指定が必要。
        ・・・
    End Class
    <Serializable()> Public Class SyohinCd ' ★ <Serializable()> の指定が必要。
        ・・・
    End Class
    [Serializable()] public class JutyuCd { // ★ [Serializable()] の指定が必要。
        ・・・
    }
    [Serializable()] public class SyohinCd { // ★ [Serializable()] の指定が必要。
        ・・・
    }

invokeLocal は、Local および Central フックメソッドの中では使えません。


ある画面フックメソッドの中で invokeLocal を用いる場合、その画面またはその画面内の項目に関する Local フックメソッドは呼び出すことができますが、他の画面または他の画面内の項目に関する Local フックメソッドを呼び出すことが禁止されています。


ある項目フックメソッドの中で invokeLocal を呼び出す場合、その項目が属する  画面または同じ画面内の項目に関する Local フックメソッドは呼び出すことができますが、他の画面または他の画面内の項目に関する Local フックメソッドを呼び出すことが禁止されています。


フックメソッド Local の中では、invokeLocal および invokeCentral を呼び出すことが禁止されています。 また、新たにフォームを ShowDialog したり Show したりするとセントラル側の呼出しを発生させるので禁止されています。


◇ ログの取得

Debug 構成においては、FormBase のプロパティ DebugFormHook および DebugItemHook を True にすることによって、それぞれ画面フックメソッドおよび項目フックメソッドのログをとることができます。 同様にプロパティ ShowTransferDataSize を True にすることによって、転送データサイズのログをとることができます。

ログは、統合開発環境 VS2008 の出力ペインに表示されます。


ローカル側のログをとるには、以下の例のように画面フックメソッド BeginPrg でログを開始させると、開始時点からのログをとることができます。

    Friend Function BeginPrg(ByVal fB As FormBase) As Boolean

#If DEBUG Then
        fB.DebugFormHook = True
        fB.DebugItemHook = True
        fB.ShowTransferDataSize = True
#End If

        Return FormBase.BEGINPRG_Allow
    End Function

    internal bool BeginPrg( FormBase fB ) {

#if( DEBUG )
        fB.DebugFormHook = true;
        fB.DebugItemHook = true;
        fB.ShowTransferDataSize = true;
#endif

        return FormBase.BEGINPRG_Allow;
    }

セントラル側のログをとるには、画面フックメソッド BeginPrgALcl でログを開始させると、開始時点からのログをとることができます。


◇ スマートデバッグ

「スマートデバッグ」とは、ツーピースをワンピースのように、すなわち統合開発環境 (VS2008) を一つ使うだけの形態で、デバッグ・テストを実施する手法です。従来は、ツーピースのデバッグを行うには、統合開発環境 (ローカル側とセントラル側それぞれに) 合計二つを立ち上げて、ギッタンバッコンしながら作業することが必要でした。これに対して、スマートデバッグ手法を用いると、統合開発環境は一つだけでスマートにデバッグできるようになります。

統合開発環境は一つですが、ローカル側にもセントラル側にもブレークポイントを設定することができ、ツーピースとしての動作をきちんとさせることができます。

また、ローカル・セントラル間で coherent 制御がなされていない変数については、ローカル側で止まったときには、ローカル側の値を示しますし、セントラル側で止まったときには、セントラル側の値を示します。

以前から二段階デバッグ手法、すなわち、まずワンピースでデバッグを行い、次にツーピースに生成し直して追加のデバッグをするという方法がありました。この二段階デバッグ手法は二度手間になるので、好まれなかったかもしれません。この問題だけでなく、ワンピースでデバッグしても、ツーピースでは動かないかもしれないというのも問題でした。

こうした問題をもつ二段階デバッグ手法に比べて、スマートデバッグは、まぎれのないツーピースでのデバッグです。すなわち、スマートデバッグを行えば、ツーピースでのデバッグができたことになります。したがって、後は本番の exe や dll を作成しての最終テストが残るだけです。

ワンピースのプログラムを早く動作させたいときには、最初にワンピースでデバッグを行い、次にスマートデバッグをすることをお勧めいたします。そして、ワンピースでの動作は不要だという場合には、最初からスマートデバッグをすることをお勧めいたします。

スマートデバッグ、つまりツーピースのプログラムをあたかもワンピースのようにデバッグできるようにする機能について研究・開発を進めてきましたが、結局のところ、VS2008 の機能を利用するだけで実現できますし、そうするのが最も素直であるとの結論に達しました。

特に細工を施すことをせずに、単にスマートデバッグ用のソリューション (Sds: Smart Debug Solution) を一つ作成するだけで、スマートデバッグ機能が実現できることが分かりました。ローカル側でもセントラル側でもエディタのインテリセンス機能が効きますし、ブレークポイントも設定できます。

なお、VB の場合は、ワンピースでのデバッグに似た形でスマートデバッグ機能が実現できるのですが、C# の場合はかなりの制限が付くのは残念なことです。これは、VS2008 の機能が VB と C# で異なるためであり、今のところしかたないことだと考えています。

前置きはこのくらいにして、サンプルプログラムをご覧ください。サンプルプログラムは Jutyu2 と Jutyu3 の二つがありますが、Jutyu2 は単純な例で、Jutyu3 は他のプロジェクトを参照する少し複雑な例です。なお、ここでは VB に関する説明を中心にして、C# の場合は省略します。

そして、ここでは単純な方の Jutyu2 について、詳しくご説明します。

従来、ツーピースのデバッグは、Jutyu2Cnt.sln と Jutyu2Lcl.sln という二つのソリューションを動作させるという方法で行っていました。つまり、二つの VS2008 を起動してデバッグをしました。なお、この方法を「ツーピースデバッグ」と呼ぶことにします。

スマートデバッグの場合は、Jutyu2Sds.sln という一つのソリューションを動作させるだけで、デバッグを実施することができます。つまり、一つの VS2008 を起動するだけでデバッグを行えるのです。

Jutyu2Sds.sln という一つのソリューションをご覧いただくと分かるのですが、このソリューションには、ローカルソリューションに含まれるプロジェクトとセントラルソリューションに含まれるプロジェクトがすべて含まれています。つまり、一つの Sds ソリューションの中に関係するすべてのプロジェクトを含めてしまうのです。これは、VS2003 ではできなかったことです (エラーが発生してしまっていました) が、VS2008 からエラーだと見なされないことになりました。そこで、これを使うことにしました。なお、ローカルおよびセントラルソリューションに共通のプロジェクトがあるかもしれませんが、それらはまとめて一つのプロジェクトとみなして Sds ソリューションに組み込むことになります。当然のことですが、二つの同じプロジェクトを Sds ソリューションに組み込むわけではありません。

さて、こうして、すべての関係プロジェクトを収容した Sds ソリューションを作成してデバッグを開始するのですが、その起動方法には2種類があります。シングルスタートアッププロジェクトとマルチスタートアッププロジェクトです。名前が少し変ですが、これはマイクロソフト社が、プロジェクトとソリューションを混同しているためです。

シングルスタートアッププロジェクトとは、スタートアッププロジェクトが一つのだけのソリューションという意味であり、マルチスタートアッププロジェクトとは、複数のスタートアッププロジェクトをもつソリューションという意味です。複数といっても、ここで使うのは、スタートアッププロジェクトを二つにするだけで、三つ四つを使うことはありません。

これらに関しては、Jutyu2Sds.sln というソリューションのプロパティをご覧いただくと分かります。

これで準備が整ったので、通常のように VS2008 に向かって「デバッグ開始」の指示をしてみましょう。(デバッグ開始の前にソリューションのリビルドを行ってください。ビルドではなくリビルドです)。すると、セントラル側とローカル側の両方が同時に起動されて、デバッグ開始となります。

ここで、ブレークポイントを設定してみましょう。例えば、商品コードというモジュールは、ローカル側にもセントラル側にも含まれていますが、どちら側のものでもかまいませんから開いて、ブレークポイントを設定してみましょう。(ご注意ですが、ローカル側およびセントラル側両方の商品コードは同時には開けません。)

たとえば、ローカル側の Function 応答表示 およびセントラル側の Function 入力チェック にブレークポイントを設定してみます。

こうしてから、受注計上アプリの商品欄に適当な値をインプットすると、両方のブレークポイントが効くことが分かります。

受注計上アプリを終了させると、ローカル側は終了しますが、セントラル側は、次の起動を待つ状態に入ります。ここで、セントラル側のコマンドプロンプトウィンドウに EXIT コマンドをインプットして終わらせることができます。あるいは、終わらせないで、ローカル側を再度起動することもできます。すなわち、VS2008 のソリューションエクスプローラの中のプロジェクト Jutyu2Lcl を反転状態にして、マウスの右クリックで、[デバッグ] - [新しいインスタンスを開始] という操作をすると、ローカル側が起動されます。