Visual Basic 業務アプリ構築法 第27回

共通処理と標準モジュールの利用
長谷川裕行
2000/07/11

長谷川 裕行 (はせがわ ひろゆき)
有限会社 手國堂 代表取締役
http://www.hirop.com/
テクニカルライターとして活躍。プログラミングに関する著書多数、DB Magazineなどにも多くの記事を提供している。

アプリケーションの規模が大きくなってくると、開発や保守を容易にするため、内部の機構を役割ごとに分割する必要が生じます。これがモジュール化――モジュール別開発です。
VBではフォーム単位のモジュール化が自然と行われまが、すべてをそれに任せてよい訳ではありません。合理的な機能分担について考えましょう。


複雑になれば細分化する

よほど単純でない限り、アプリケーションは内部に複数の機能を抱え込んでいます。個々の機能が一定の目的のために連携することで、複雑な構造が出来上がっているのです。


- 業務アプリの構造 -

在庫管理、販売管理、収支管理、勤怠管理、給与計算…業務アプリケーションには、たくさんの種類があります。教育機関の生徒・学生管理や、自治会の会費管理などもその仲間と言えます。
個々のアプリケーションがおおよそどのような形態となるかは、この連載をお読みのみなさんならお分かりでしょう。
例えば「販売管理」なら、以下のような構造になるはずです。

基本処理 販売情報の入力
日次処理 1日の集計など
月次処理 1箇月の集計、データの集約など
随時処理 商品検索、顧客検索、データ集計など
管理処理 各種マスターの保守など

ひとくちに「販売管理」といっても、このように様々な処理から成り立っています。


- 小さな処理の集合 -

個々の具体的な処理は異なりますが、販売管理以外のアプリケーションも「小さな処理の集合」であることに変わりありません。業務アプリケーションは、そのほとんどが複数の小さな処理から出来上がっています。1つの小さな処理だけでできているものは、まずあり得ません。
ワープロや表計算ソフトなども、「新規作成」「フォントの変更」「印刷」などたくさんの小さな処理から構成されています。しかし、これらアプリケーションを操作するユーザーの目的は千差万別なので、個々の機能は汎用的で独立しています。
一方業務アプリケーションは、上に掲げた例でもお分かりのように、個々の機能が特定の目的のために連携しています。


- ワープロと販売管理の違い -

例えばワープロなら、開いている文書をどのように処理するかは、すべてユーザーに委ねられているため、メニューやツールバーから様々な機能を実行できるようになっています。
しかし販売管理処理では、「販売の情報を記録し、取りまとめる」という目的のために、各機能が分類・整理されているため、販売データの入力中にフォントを変更したり、商品マスターの保守中に売り上げの集計をしたり…といった操作を考える必要はありません。
これは、そういったことが機能的にできない――ということではありません。業務アプリケーションでも、メニューやツールバーで汎用的な処理を行わせることは可能です。
が、特定の目的を遂げることが使命となる業務アプリケーションでは、基本的に「ある処理を実行中に、他の処理を行わない」という了解の下に処理を組み立てることが可能です。


- 基本構造は変わらない -

このように、ワープロなどの汎用アプリケーションの構造と業務アプリケーションの構造とは、大きく異なります。が、それはあくまでユーザーの側、つまり外から見た違いです。アプリケーションの内部から見れば小さな処理が集まって、大きな処理を組み立てていることに変わりありません。
アプリケーションの機能を分解していくと、小さな機能に分割できます。それは、ワープロの「新規作成」や「印刷」メニューだったり、販売管理の「データ入力」や「商品マスターの保守」だったりします。


VBと機能分担

ここからは、ユーザーの視点ではなく、開発者の視点でアプリケーションを内側から眺めていきましょう。


- 個々の機能とフォーム -

VBでは、1つのアプリケーションは1つのプロジェクトとして管理できます。が、アプリケーションを構成する各種機能を、すべて1つのコードウィンドウにまとめてしまっては、保守が大変です。
ソースコードは長くなり、ごく一部の機能だけを手直ししたい場合でも、ウィンドウを延々とスクロールして目的の箇所を探さなければならなくなるでしょう。
こう書くと、多くの方は「そんなことないよ。VBではフォームごとにコードウィンドウも別になるじゃないか」と思われるでしょう。その通りです。VBでは、各種機能がフォーム単位で独立した構造となります。


- フォームモジュールとコードモジュール -

VBでは、まずフォームをデザインしフォーム上のコントロールに発生したイベントの処理をコードとして記述するというスタイルで開発するため、 フォームウィンドウとコードウィンドウとが1組になっています。フォームは「フォームモジュール」コードは「コードモジュール」と呼ばれ、それぞれプロジェクトを構成するオブジェクトです。
さらにフォーム上のコントロールや、コードに記述するプロシージャも、各オブジェクトを構成する部品と見ることができます。このように、アプリケーションは全体が個々の機能から構成され、個々の機能もさらに小さな機能から構成されているのです。
この構造はアプリケーションだけではなく、例えばパソコンのような機械類や、書籍・雑誌などの本にも当てはまります。


- フォームのないコードも存在する -

VBではフォーム単位で機能が分担されるため、プログラマーはアプリケーションが機能の集合であるということを、強く意識する必要はありません。セオリー通りにアプリケーションを組み上げていけば、自然と機能別の構造が出来上がってしまいます。
しかし、すべてを「フォーム単位の区切り」に任せてしまうことはできません。VBが手助けしてくれる機能分担の構造は、フォームを中心とした処理に限られます。
アプリケーションの中には、フォームを持たない「コードだけの機能」も存在します。例えば「帳票の印刷処理」の中枢部分では、印刷のためにプリンタを制御する処理を記述するだけで、その元となるフォームが存在しません。
プ リンター選択や用紙設定のためのフォームは補助的なダイアログボックスであり、帳票印刷そのものの基点となる訳ではありません。
  このような「フォームを持たない処理」は、フォームモジュールと連携したコードモジュール――つまりフォームやコントロールをダブルクリックしてオープンするコードウィンドウに記述するのではなく、それらとは別のモジュールとして用意する必要があります。

図1:VBによるアプリケーションはフォーム中心にモジュール化される


標準モジュールと共通処理

フォームを持たないコードだけのモジュールを、「標準モジュール」といいます。多くの場合、標準モジュールには、各フォームとそれに連携したコードモジュール――つまり「フォームという“顔”を持っている処理」――から共通して参照される処理、あるいはそれらのどこにも属さないような処理を記述します。


- フォーム、コードと標準モジュール -

販売管理処理を例に、そのメニュー構造と、フォームモジュール、コードモジュールの関係を示しておきましょう。

表1:販売管理処理の構造


- 共通の処理が散在している -

こうして全体をざっと見渡すと、各処理単位ごとにフォームが存在していることが分かります。1箇月の集計を行う処理ではフォーム“frmMonthSum”がオープンし、実際の処理はそのコードモジュールに記述することになるでしょう。商品の追加や削除、価格の変更などを行う場合は、フォーム“frmItemMnt”をオープンし、そのコードウィンドウに実際の処理を記述することになります。
しかし、すべての処理が各フォームに関連したコードモジュールに記録されるわけではありません。そうすることも可能ですが、例えば、日次処理を行う“frmDairy”から実行される「入出庫一覧の印刷」処理、月次印刷処理“frmMonthUpdate”から実行される「月ごとの集計結果の印刷」処理、在庫数調整処理“frmStockMnt”から実行される「在庫一覧表の印刷」処理など、印刷の基本部分を共有できる処理も存在します。
印刷対象のデータやそのレイアウトは異なっても、プリンタの選択やプリンタにデータを送る処理などは、どの印刷処理にも必要な共通した処理です。それらを各コードモジュールに個別に記述するのは無駄であるばかりでなく、修正に手間がかかる上、余計な間違いが入り込む可能性も高くなります。


- 共通処理をまとめる -

プログラム設計の基本は、「同じコードは1箇所にまとめる」ことです。今更説明するまでもないでしょう。
上記の例では、この他にもデータベースの接続とオープン日付の入力処理など、複数のフォーム・コードモジュールから利用できる処理はいくつか存在します。
これらは、特定のフォームやコードモジュールに依存する処理ではありません。というより、共通の処理として「どのフォームやコードにも依存しないよう」記述しなければならないはずです。
こういった共通のコードを保存するモジュールが「標準モジュール」です。
標準モジュールを利用するには、まず標準モジュールをプロジェクトに追加しなければなりません。あとは、追加した標準モジュールに、共通の処理を記述するだけです。
標準モジュールはコードだけでフォームは存在せず、拡張子.basのファイルとなって保存されます。

画面1:標準モジュールを追加する


- 基本はPublic -

標準モジュールでも、他のコードモジュールと同じように変数の宣言とプロシージャの定義ができます。前回説明したように、変数やプロシージャにはPrivateとPublicが存在します。

Private:他のモジュールから参照できません
Public:他のモジュールから参照できます

標準モジュール内の変数やプロシージャは「他のモジュールから共通して参照」できなければなりません。従って、主要なグローバル変数やプロシージャには、Publicキーワードを付けて宣言する必要があります。
Privateキーワードを付けると、いくら標準モジュールでも他のモジュールからは参照できない「隠れた変数、隠れたプロシージャ」となってしまいます。
もちろん、モジュール内で下請け処理として利用するプロシージャや、モジュールの中だけで使用される変数はPrivateとして宣言します。こうすることによって、プロジェクト全体で利用する変数とプロシージャだけを外部に公開し、他はすべて隠蔽できます。


- どのフォームにも属さないコードの集合 -

標準モジュールを用いなくても、すべてのモジュールから共通して参照される変数やプロシージャは作れます。コードモジュール内でPublic宣言すればよいだけです。しかし、コードモジュールはフォームモジュールと関連していることを考えれば、これが良い方法であるとは言えません。
VBでは、まずフォームモジュールによって「画面単位」で処理を分割します。コードモジュールでは、分割された各画面に関連する処理を記述します。それ以外の――フォームとは直接関連しない、あるいは他のコードからも利用される処理までそこに記述してしまうと、全体の構造を見渡すことが難しくなります。
全体に共通する処理を括り出し、それを「どのフォームにも属さない」コードの集合としてまとめるために、標準モジュールが存在します。

画面2:コードモジュールはフォームモジュールと関連している
画面3:標準モジュールには関連するフォームが存在しない


標準モジュールの使用例

今回は、サンプルとして「映画データベース」を紹介しておきます。mdbファイルをアクセスし、データの追加・削除・修正の他、キーワードによる検索とデータの一覧印刷ができます。

この中のModule1.basが標準モジュールです。内容はリスト1のようになっています。
mdbファイルのパスを取得したり、各フォームのテキストボックスにフィールドを設定したりする処理を、すべてPublicプロシージャとしてまとめてあります。
取得したファイルのパス名は、Publicグローバル変数として宣言しています。
リスト2は、レコードの追加を行うフォーム“frmAddNew”の初期化部分です。ここで標準モジュールの“SetDbName”と“SetDbFields”を呼び出し、初期化を行っています。
このサンプルでは、標準モジュールの利用以外に、印刷処理やユーザーコントロールなど、業務アプリケーションの開発に重要な機能を随所に取り入れています。個々の機能の具体的な内容は、回を追って紹介していくことにしましょう。

画面4:映画データベース~検索や印刷もできます
リスト1:映画データベースの標準モジュール
リスト2:レコードの追加処理(フォーム名frmAddNew)の初期化部分



DownloadVBプロジェクトファイルのダウンロード
(LZH形式 40.9KB)
Copyright © MESCIUS inc. All rights reserved.