Javaコードの診断: 拡張可能アプリケーションの設計 第1回
ブラック・ボックス、オープン・ボックス、またはガラス・ボックス: どんな場合にどれがふさわしいか?
![]() |
|
レベル: 中級
Eric Allen, Ph.D. candidate, Java programming languages team, Rice University
2001年 09月 01日
Eric Allenによるこの記事と今後のJavaコードの診断 のシリーズでは、新しいシステムをどれほど拡張可能なものにするべきか、拡張性はどんな場合に最もよく当てはまるか、そして拡張性と他の要素、とりわけテスト可能性との間にどんな関係があるかについて論じます。その第1回であるこの記事では、ソフトウェア・システムを拡張可能にするためのさまざまな方法、そして拡張可能の各方法はどんな場合に最も有効かについて説明します。
ますます多様化する情報処理に対応できるソフトウェア・システムの必要性が増大するにつれて、新規コード・プロジェクトの生産コストを削減する方法を追求することは、ソフトウェア会社にとって大きな関心事となっています。そのための最も明らかな方法の1つは、他のプロジェクトのコードの再利用を推進することです。
その点で、プログラマーが新しいシステムを設計する際には、次の2つの点がよく問題になります。
- そのシステムは、どの程度拡張可能であるべきか?
- そのシステムは、どの程度まで拡張可能にできるか?
コードの再利用が最もうまくいくのは、元のシステムが拡張可能なものとして設計されている場合です。そうでない場合には、コードの再利用が難しくなり、生産性を上げることは困難です。しかし、拡張可能な設計をするためには、ソフトウェア設計に関して、あらゆる点で新しい考慮事項を追加することになります。
![]() |
|
この記事では、将来のプロジェクトに備えてソフトウェア・システムを拡張可能にするためのいくつかの方法について説明します。
本論に入る前に、「私は、すべての場合での、あるいはほとんど全ての場合における拡張性を考慮した設計を支持している」わけではないことをはっきりさせておきたいと思います。拡張性を考慮した設計の多くは、パフォーマンスやテスト可能性など、他の考慮事項を妨げるものとなることがよくあります。テスト可能性の点で最高のシステムは、しばしば最もシンプルなシステムですが、拡張可能な設計の場合、システムがかなり複雑になることは少なくありません。
幸いなことに、拡張可能性の点で最高である設計が最もシンプルとなる場合もあります。しかし、そのような場合は極めてまれです。
そのため、拡張性を考慮したストラテジーを採用するのは、それによる利点が確実にコストを上回る場合だけにするようお勧めします。つまり、特定の方法でシステムが拡張されることがわかっている 場合です。
エクストリームプログラミングの文献の中には、拡張性の追加をストック・オプションの購入と比較しているものがよく見受けられます。つまり、ストック・オプションを早期に購入しておけば、後になってシステムを拡張するのが容易であるというわけです。後でその権利を行使すれば、大もうけできます。
しかし、もしその権利を行使することがないなら、権利を購入する費用がかかるだけで、そこから得るものが何もないことになります。というわけで、"買い手の皆さん、ご用心!"
次に、拡張性 という用語のさまざまな定義について考慮しておきましょう。プログラムの拡張性について論じる場合、拡張性ということには本質的に3種類の意味があります。ブラック・ボックス 拡張性と、2種類のホワイト・ボックス 拡張性です。図1 に、それらの拡張性の違いが示されています。
![]() ![]() |
|
ブラック・ボックス拡張性とは、元のコードを直接に拡張することなくプログラムを拡張する方法のことです。通常これは、システムの拡張を可能にする構成言語やウィザードを使用することによって実現されます。
その一例は、さまざまな納税申告用紙を指定するための構成言語が含まれている税金処理プログラムです。政府が新しい申告用紙を提示したなら、構成言語によってその新しい申告用紙の構造を指定することによって、簡単にシステムを拡張できます。
ブラック・ボックス拡張性は、オリジナルの開発チームのビジネス・モデルにおいて次の2つのことが必要となる専売的なコンポーネントやフレームワークの場合に、最もよく当てはまります。
- プログラムが専売的であること (オープン・ソースでない)
- コンポーネントの機能をカスタマイズする点で、外部の開発者にある程度の柔軟性が与えられていること
ブラック・ボックス拡張性のあるシステムの例として、ユーザー定義のスクリプトやマクロを使用できるプログラム (EmacsやMS Officeなど) が挙げられます。
![]() ![]() |
|
ホワイト・ボックス拡張性は、ソース・コードの変更や追加によってプログラムを拡張する方法のことです。私は、ホワイト・ボックス拡張性を、さらにオープン・ボックス とガラス・ボックス の2つのサブカテゴリーに分けることにしています。
オリジナル・ソース・コードの修正が可能な場合、私は、そのシステムのことをオープン・ボックス拡張可能と言っています。もちろん、そのようなプログラムは原則としていくらでも拡張できるわけですが、拡張の内容によってその難しさが異なります。
オープン・ボックス拡張性の研究は、必要に応じてプログラムを変更できる場合に、さまざまな種類の拡張をどう活用するかということが中心になります。これは、独自に開発した製品の次期バージョンを生産する開発チームにとって最も関係のある拡張形態です。
場合によっては、既存のオープン・ソース・ソフトウェアの活用を考えている開発者にとっても、この種の拡張性を検討する価値があります。しかし、オープン・ソース・システムをこの方法で拡張することには、多くの問題があります。
最大の問題点は、"オフィシャル" メインテナンス・チームがそのソフトウェアの新規バージョンをリリースすることにした場合にどうするか、ということです。それによる変更点を独自の変更と組み合わせることは、困難で時間のかかる作業になる可能性があります。独自に変更を加えた実際のコードが不整合を引き起こさないようモジュラー化されたシステムでさえ、新しいコードで不変とされている部分があなたの独自の変更によって壊されることがないようにするのは、非常に難しいことです (とはいえ、コードに単体テストが付随しているなら、この問題はかなり改善される可能性があります)。
ガラス・ボックス拡張性とは、あるソフトウェア・システムのソース・コードの表示は可能だが修正はできない場合に、そのシステムを拡張する方法のことです。
外部的に維持されているオープン・ソース・コードの修正に関する前述の問題点のため、そのようなコードでは、可能な限りガラス・ボックス拡張だけを使用するのが望ましいでしょう。よくあるガラス・ボックス拡張可能システムの典型的な例は、JUnitです。どの単体テストも、オリジナル・コードに対する拡張と見ることができます。
図1. 拡張作業でのコードのアクセス可能性に応じた異なるアプローチ
|
これらの各種の拡張性は、それぞれ特定のコンテキストで有用です。いくつかのコンテキストについては、すでに述べました。たとえば、"外部" 開発者がプログラムを拡張することが認められている専売的なソフトウェア (元のコードの表示は認められていない) の場合は、ブラック・ボックス方式が適しています。
元のコードが表示や修正の可能なオープン・コードの場合は、ホワイト・ボックス方式のいずれかが適しています。
もちろん、状況に応じて、ソフトウェア設計に対する影響もそれぞれにあります。それでも、1つのシステムに複数の形態の拡張性を採用することが可能な場合があります。
次回には、ホワイト・ボックス拡張性に関する論議を発展させる予定です。さらにその後の記事では、複数の種類の拡張性を使用したシステムの例を紹介します。
- ACMのWebサイトにある記事 "Object-Oriented Framework Development" では、フレームワーク内で、さまざまな形でアプリケーションを再利用することについて論じられています。
- JUnitのホーム・ページには、プログラムのさまざまなテスト方法について扱った、たくさんの興味深い記事へのリンクや、JUnitの最新バージョンがあります。
- Ericの「Javaコードの診断」の全記事をご覧ください。その多くは、さまざまなバグ・パターンを扱っています。
- バグ・パターン: Javaプログラムで頻発しがちなバグの分析と修正
- 「宙ぶらりん複合型」バグ・パターン: ヌル・ポインター例外の最もよくある原因を鎮圧する
- 「ヌル・フラグ」バグ・パターン: 例外状況を表すフラグとしてヌル・ポインターを使うことを避ける
- 「二段たどり」バグ・パターン: 再帰的なクラス・キャストという概念上のエラーを最初から克服する
- うそつきビューのバグ・パターン: GUIの最良の友になってうそつきビューを暴き出しましょう
- 破壊工作データのバグ・パターン: 隠れたデータ爆弾が奇妙なクラッシュの原因かもしれません
- 破綻したディスパッチのバグ・パターン: 引き数のアップ・キャストによって、不正確なメソッドの呼び出しを修正する
- Javaコードのパフォーマンスを向上させる: 末尾再帰変換はアプリケーションの速度を向上させる可能性はあるが、すべてのJVMで可能な操作ではない
- 正しいメソッド呼び出しのためのRecorderによるテスト: メソッドの呼び出しを順序正しく行うために、ユニット・テストのためのRecorderを記述する
- 型詐欺師のバグ・パターン: タグを使用したオブジェクトの型の区別は、ラベルの貼り違えにつながる可能性がある
- クリーンアップ・コード散在バグ・パターン: リソースの獲得および解放を同時に実行する
- 虚偽の実装というバグ・パターン: 第1回: 前提とした不変条件がインターフェースの破壊を招くこともある
- 虚偽の実装というバグ・パターン: 第2回: 表明とユニット・テスト - バグを除去するための実行可能なドキュメンテーション -
- 「みなし子スレッド」バグ・パターン: マスター・スレッドが自滅し、その他のスレッドが生き残っていると、どうなるか?
- 「テスト可能な」アプリケーションの設計: 以下に示す7つの原則は、テストを念頭においてコード設計を行う際のもとになるものです
- developerWorks Javaテクノロジー・ゾーンには、Javaに関するその他の参考文献があります。
![]() | ||
| ![]() | Eric Allen氏は、コーネル大学でコンピューター・サイエンスおよび数学を専攻し、A.B.(Bachelor of Arts)を取得しました、また現在は、ライス大学、Javaプログラミング言語チームの博士課程に在籍しています。彼の研究対象は、Java言語のソース / バイトコード・レベルでのセマンティック・モデルおよびスタティック分析ツールの開発です。また現在は、NextGenプログラミング言語 (ジェネリック・ランタイム・タイプを持つJavaの拡張言語) のためのソース・ツー・バイトコード・コンパイラーを作成しています。 |
![](http://www.ibm.com/i/c.gif)