連載:熱血VBプログラマ応援団 |
|
− 今回のご相談 − |
||
|
Moduleとオブジェクトはどう違うのか
まず、Module(VB.NETの言語仕様では、「標準モジュール」と呼ばれているもの。ここではModuleという表記で通します)は、決して時代遅れの悪いものと決めつけるべきではないと思います。ここでは、そのことについて書いてみましょう。
その前に、そもそもModuleとはなんぞや、そして、7人のVさんが気にされているClass(クラス)とはどこが違うのかを確認しておきましょう。
標準的なVBプログラミングでは、まずフォーム上にコントロールを並べ、そのフォームの中に変数やイベント・ハンドラとなる手続きなどを書き込んでいくことになります。しかし、しばしば特定のフォームとは独立した変数や手続きなどを記述する必要が発生します。そのために使われるのが標準モジュール、通称Moduleというわけです。
VB.NET言語仕様から標準モジュールを調べると、「6.6 標準モジュール」に以下のように書かれています。
標準モジュールは、メンバが暗黙的に Shared である型です。
しかし、これを見てもよく分かりませんね。クラスが分かっている方なら、すべてのメンバが静的(Shared)であると見なされるクラスのようなもの、と説明すると分かるかもしれません。しかし、クラスをよく知らない読者には、これもちんぷんかんぷんな説明でしょう。
以下、オブジェクト指向用語に不慣れな読者への配慮と、正しい定義を正確に伝えるには誌面が足りないことにより、「あえて」雰囲気をつかむことを優先した説明を行います。このため、必ずしも正しくないことも書きます。もちろん、読者の誤解を生む可能性はありますが、本記事の中心的な読者のために必要な配慮と考えて行います(もちろん何でもよく知っているマニアの方ではありません)。
大ざっぱにいえば、Moduleとは、グローバル変数と、そのModule自身以外のどこにも属さない独立したメソッド(あるいは手続き、関数と呼んだ方が分かりやすければ、それら)、およびプロパティなどのプログラムを1つにまとめるための機能、と理解してください。
次に、クラスとは何かを簡単に説明しておきましょう。クラスとはオブジェクトの設計図に当たるものです。ここでは、クラスという言葉は忘れて、オブジェクトという言葉だけ使いましょう。オブジェクトは、(これも不正確ではありますが)以下のようなものだと、ここではしておきましょう。オブジェクトとは、データとプログラムをセットにした1つの小さな塊で、あらかじめ用意された設計図によっていくつでも生成できるもの、とします。
ここで、オブジェクトとModuleを比較してみましょう。Moduleのグローバル変数がオブジェクトのデータに対応し、両者が含むプログラムを同じものと考えるなら、両者はよく似ています。Moduleもまた、「データとプログラムを1セットにしたもの」と見ることができるのです。しかし、「あらかじめ用意された設計図によっていくつでも生成できる」という機能性が、Moduleには欠落しています。つまりModuleは、全体の中で1つしか存在できません。
このように考えると、明らかにModuleとはオブジェクトの機能制限版でしかなく、使う意味のない過去の遺物のように見えるかもしれません。しかし、それを結論として思考停止してしまっては進歩がありません。たとえ誤っていようと、さまざまな可能性を探究してこそ、未来は開けるのです。
グローバル変数は使うべきではない
Moduleは「データとプログラムを1セットにしたもの」と見ることができます。しかし、本当にそう見てよいのでしょうか。Moduleでのデータとプログラムの役割は、オブジェクトでの役割と同じなのでしょうか。
私はそうではないと思います。Moduleに含まれるデータとプログラムは、オブジェクトに含まれるそれとはまったく違う性質や役割を持ったものです。よってここでは、Moduleに含まれるデータやプログラムそれぞれの性質と役割を明らかにして、そこからModuleとオブジェクトの違いを検討してみたいと思います。
まず、Moduleに含まれるデータは、いわゆるグローバル変数です。これは、基本的には使うべきではない変数だと思います。必要悪としてのみ存在意義があると思います。
なぜ、グローバル変数を使うべきではないのか。その理由として、いろいろなことがすでに語られています。例えば、C言語について書かれたものではありますが、「プログラムの解読や改造が困難になり、バグが発生しても退治しにくくなる」と説明しているものが一例です。
現在私が個人的に感じている「グローバル変数を使うべきではない」最大の理由は、テスト駆動開発との相性の悪さです。テスト駆動開発では、大量の単体テストを一気に自動実行しますが、グローバル変数があると、前に実行したときに設定した値が次のテストの初期値となってしまい、適切なテスト結果を得られない危険性があります。これを回避するには、個々のテストの前にグローバル変数を再初期化するコードを入れねばなりません(NUnitというツールを使用した場合は、TestFixture属性の付いたクラスごとに入れねばなりません)。
それを考えると、グローバル変数抜きでプログラムが記述できるなら、それに越したことはないと思います。Visual Studioの将来のバージョンにテスト・ツールの機能が入るといった情報もあります。それによってテスト駆動開発が幅広く普及する可能性もあると思うので、これを配慮する価値はあると思います。
しかし、それにもかかわらず、グローバル変数が必要とされる状況が確かにあります。例えば、取得に時間がかかる情報を保持しておいて再利用する、といった状況で、やむを得ずグローバル変数を使う場合もあります。しかし必要悪と前述したとおり、やはり使わないで済むなら使わない方がよいものだと思います。
データを持たないメソッドの存在意義
さて、Moduleに含まれるデータは使うべきではない存在だとして、次にModuleに含まれるプログラムについてはどうでしょうか。
これについては、(ある種の)XML的な側面から考えてみたいと思います。
コンピュータを利用するうえでいつも登場するプログラムとデータ。この2つのうち、どちらが主役であり、どちらが脇役なのでしょうか。
コンピュータの歴史を見ると、初期の時代には、明らかにプログラムが主役であり、データは脇役でした。だれもがプログラムに注目し、データはプログラムを使うことで作られるものにすぎませんでした。データとは重要なものですが、それにふさわしい扱いを受けていなかったといえます。
それに対して、オブジェクト指向プログラミングでは、データとプログラムは1セットにしてオブジェクトという単位にまとめよう、と考えられるようになりました。データとそれを操作するプログラムがセットになるため、プログラム開発でデータの存在は常に意識されます。つまり、データとプログラムは同格の存在になったのです。軽んじられていたデータの価値が、ようやくプログラムと同格のレベルまで上がってきました。
しかし、これで終わりというわけではありません。例えば、XML的な視点からいえば、プログラムは脇役にすぎず、データの方が主役である、という考え方もあるからです。例えば、数十年間保管される公文書をXML文書として記述するようなケースを考えてみましょう。その場合、1つのプログラムがその文書を扱い続けることはあり得ません。時代が変われば、環境もニーズも変わるので、新しいプログラムを作成しなければならないでしょう。しかし、データの方は変化することなく残り続けるのです。むしろ、公文書の場合は、保管する意義から考えて変化させてはならない、と見るべきでしょう。
すると、データをプログラムの都合で設計することなどできないことになります。まず、プログラムと関係なくデータを設計し、XML文書を作成します。その後で、それぞれの時代の必要に応じて、そのデータを処理するプログラムを作成することになります。
このような考え方を取った場合、オブジェクト指向プログラミングのように、データとプログラムを1セットのものとして扱うことは得策とはいえません。むしろ、内部にデータを持たない方が扱いやすい、とすらいえます。もちろん、内部処理用の変数などを持つことはよいのですが、一時的な情報を記憶するものに限られるということです。永続的な情報は、常にソフトウェアの外部にあって、プログラムは必要なときにそれを参照する形に組むことが基本となります。
データを持つ必要がなければ、要するにオブジェクトよりもただのメソッドの方がよい、ということになります。そのように考えると、Moduleのどこにも属さない独立したメソッドは、オブジェクトよりも、このようなモデルに親和性が高いと見ることもできるでしょう。つまり、Moduleこそが、クラスよりも新しい世代のプログラミングのツールになるかもしれない、ということです。
もちろん、このような考え方が正しいかどうかは分かりません。しかし、Moduleという機能が存在することにより、このようなプログラミングへのチャレンジがスムーズに実践できるプログラム言語がVB.NETである、ということはできるでしょう。
C#でModule相当の機能は実現できるか?
では、Moduleに相当する機能が存在しないC#などで、同じことを実現できるか考えてみましょう。
以下の手順を踏めば、ほぼ同じものがクラスを用いて実現できます。
-
クラスに含まれるメソッドなどにすべてstaticキーワード(VB.NETのSharedキーワード相当)を付加して静的にする
-
静的ではないコンストラクタを作成し、それにprivateキーワードを付加する(インスタンスを作成させないため)
Moduleと比較して、このような追加手順が必要になります。また手順を間違えると意図しない動作をすることもあり、弱点といえるかもしれません。
では、C#で、あるいはオブジェクト指向プログラミングで、このようなコーディングは必要とされているでしょうか。もし、必要なければ、追加手順が必要であることは弱点とはいえなくなります。
実際のソフトウェアを見ると、このようなコーディングが行われる場合があることが分かります。例えば、.NET Frameworkのクラス・ライブラリに含まれるSystem.Mathクラス(三角関数などの数値処理メソッドを持つクラス)は、privateキーワード付きのコンストラクタが含まれていて、まさに上記のような構造になっています。System.Mathクラスがいかなるプログラム言語で書かれているかは分かりませんが、もし同じものをVB.NETとC#で書き比べるなら、VB.NETの方がややスマートに記述できることになるでしょう。
さて、このような追加手順の必要性を弱点と見なす場合、Moduleが存在することは好ましい特徴であるといえます。しかし、利用頻度が少ないからクラス+追加手順で済ませる方がよいと考えるなら、Moduleは存在すべきではない機能であるといえます。この2つの考え方はどちらにも一理があり、どちらか一方だけが正しいと断言することはできないと思います。つまり、使い所さえ間違えなければ、Moduleにも存在意義があると考える余地があると思います。
Moduleはオブジェクト指向プログラミングへの障害となるか
残された問題は、Moduleが存在することによって、VB.NETプログラマがオブジェクト指向プログラミングの世界に入って行く障害になるのではないか、という懸念です。
私も、基本的にはオブジェクト指向プログラミングは有益なものであると思います。それを適切に活用するかどうかによって、明らかに生産性に差が出ます。
確かに、オブジェクト指向のデータとプログラムを1セットで見る視点には異論もありますが、それを踏まえても、ソフトウェアを組むための手段としてのオブジェクト指向プログラミングには大いなる価値があります(永続的でなければオブジェクトがデータを含んでいても何ら問題はないし、オブジェクト内のデータはシリアル化することで永続化することもできる)。
もし、Moduleの存在が、VBプログラマがオブジェクト指向プログラミングに習熟する妨げになるとすれば、これは問題といえるかもしれません。
しかし、その点では楽観しています。VBプログラマがオブジェクト指向プログラミングに向かうのは、従来型のプログラミングでは対応不可能になって初めて、しぶしぶ動くためではないと思うからです。つまり、実用性を重視するVBプログラマは、強制されて初めてオブジェクト指向プログラミングに向かうわけではなく、それが有益なものだということを体感した上で自らそれに向かうと思うのです。
VB.NETでは、.NET Frameworkのクラス・ライブラリというクラスの宝庫が利用可能です。これを活用することに目覚めれば、自動的にクラスを活用するプログラミングに習熟することになります。そうすると、自分で作成するプログラムも、同じようなスタイルで仕上げる方がよい、という気持ちになっていくでしょう。そうなれば、オブジェクト指向プログラミングの世界に自発的に進んでいくことになります。
そんな楽観論に頼った明るい未来像は信じられませんか? 人は楽な方に流れますから、オブジェクト指向プログラミングの方が楽だと分かれば、Moduleの有無に関係なく、その方向にみんな流れていくと私は思います。
頑張れVBプログラマ、君たちが使うVisual Basic.NETは取り組む価値のある可能性に満ちたプログラム言語だ!
「熱血VBプログラマ応援団」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|