VB6VB6 でオブジェクト指向プログラミング

  • VB6

スポンサーリンク

VB6 でも、オブジェクト指向プログラミング (OOP) をお勧めします。当サイトで、公開している VB6 のサンプルコードも、オブジェクト指向を意識しております。

サンプルコード

例えば、あるフォームを表示する場合、

VB6.0 以前
    Dim cForm2 As Form2
    Set cForm2 = New Form2

    Call cForm2.Show(vbModal)

と、Form2 をインスタンス化しなくとも、

VB6.0 以前
    Call Form2.Show(vbModal)

と、直接 Form2 を操作することが可能だったりします。しかし、私はそういうことはしないようにしております。その理由を以下に述べております。

インスタンスを生成することで得る安全性

インスタンスを生成することで、確実に初期化されたものを扱うことができます。同じものを複数扱う時にはインスタンスを複製することで簡単に可能ですから安全です。

ところが、インスタンスを生成せず、直接操作してしまうとそうはいきません。アプリケーションを終了しない限りは、初期化されているという保証がありません。

暗黙的にインスタンス化された唯一のフォームを、参照している場所をすべて把握するのは困難です。オブジェクトだろうと何だろうと、変数はなるべく局所的にすべきです。同じものを制限なく呼び出せるというプログラム設計は、不具合の温床になります。

フォームはクラスである

フォームはメソッドなどにアクセス修飾子が設定できますのでクラスであると言えます。(カプセル化の概念)フォームがクラスということは、外部からフォーム内の GUI に関与してはいけないことになります。フォーム外で GUI に関する処理を記述するのは、カプセル化の概念を壊していることに他なりません。

逆に言えば、フォームで処理を記述する時は必ず GUI の処理であるべきです。ビジネス ロジックは、クラス モジュール (標準モジュール) で、GUI の処理はフォームでやるのが定石です。

プロパティを通してアクセス

フォームがクラスであるということは、フォーム内のコントロールはメンバとなります。困ったことにこのコントロールは直接触ることが可能ですが、それはやめましょう。

外部から値を参照したい場合は、プロパティを通すようにするべきです。プロパティが定義されていることで、外部から参照されていることを「明示化」できるからですクラス内のメンバは隠蔽化されるべきですから、当然といえば当然です。

無論コントロールのイベントなどを Public で公開するという行為はあってはいけないことです。昨今、そんなソースを見かけることがありますが、イベントの概念を壊すようなことはしないでください。イベントは内部的に "起きる" ものであり、自分で呼び出して "起こす" ものではありません。起こすのであれば、それはメソッドにするべきプロシージャであり、わざわざイベントにしてまで概念を壊すこともないでしょう。

オブジェクト指向言語と手続き型言語

VB6 は厳密には手続き型言語ですが、オブジェクト指向言語に近いコーディングをすることが可能です。(実際、Implements キーワードもあります)

VB が生産性が良いと言われているにも関わらず、デバッグなどに時間を浪費することがあります。それは、オブジェクト指向を (むしろ、構造化を) 意識して組んでいない場合だったりしないでしょうか?特に他人のソースは、なおさらに時間がかかってしまいます。

オブジェクト指向における継承やインターフェースの実装は大変便利ではありますが、必須条件ではありません。カプセル化による隠蔽化こそが必須条件であり、本当の恩恵なのだと考えます。

標準モジュールよりクラス モジュール

ひとまとまりの機能をクラスに集約することで、他人が見ても見やすいです。それは、外部から参照するべきもの、内部だけで処理するものが明確に分けられているからです。使用する側が意識しなくても良いものは隠蔽化することで、何をどう使えば良いか明確になります。

これは実生活でも同様です。家電製品のリモコンは、よく使う機能が前面にあり、あまり使わない機能は隠されています。複雑な機能は、クラス モジュールで実装し、欲しい機能だけを公開するのが良いと考えます。

かといって、何もかもクラス モジュールでやれば良いというものではありません。単発で使用するような汎用関数などは、標準モジュールなどを利用した方が賢明です。

標準モジュールは静的クラスのように使う

標準モジュールでもアクセス修飾子は指定できますから、静的クラスのように使用できます。とはいえ、モジュール名を省略できてしまうのが、つらいところです。

例えば、basDateTimeHelper.bas という標準モジュールの中に、GetServerDate という公開された関数があるとします。これを使用する場合、どの位置からでも GetServerDate だけで呼び出せてしまうのです。モジュール名を省略してしまうと、どの位置にある関数なのか明確でなくなるので省略しない方が良いでしょう。

かといって、ハンガリアン記法のような「basDateTimeHelper.GetServerDate」と表記しても可読性が良くないです。静的クラスのように使うのであれば「DateTimeHelper.GetServerDate」のように表記したいものです。

こういう部分にまで、ハンガリー記法 (ハンガリアン記法) を使うメリットはないでしょう。そもそも、変数を局所的に使用する設計であえば、ハンガリー記法は必要ありません。

ハンガリー記法 (ハンガリアン記法) について

ハンガリー記法は、どの位置まで有効なアクセス修飾子なのか明確でなくなるような設計である場合に必要になる記法です。オブジェクト指向で組む場合は、プライベート メンバの変数もパブリック メンバの変数も少なくなる (管理しやすくなる) 傾向にあるため必要ないです。ローカル変数の場合は普通に管理できるでしょうから、なおさらに必要ありません。(と言いつつこのサイトでは使っていますが)

それでも使うとなれば、コントロールで使うことになるでしょう。Code を表す TextBox コントロールならば txtCode、この項目の名称を表示する Label コントロールには lblCode のような使い方です。様々な方にもお話を伺いましたが、やはり皆さんも同じ考えで、コントロール以外で使用することはないそうです。

関連するリファレンス

準備中です。

スポンサーリンク