レベル: 初級 Eric Allen, Software Engineer, Cycorp, Inc.
2002年 3月 01日 Javaプログラムの実行では、普通、main() メソッドからプログラムを実行し、String[] 入力引き数を使ってパラメーターを渡すことが必要です。しかし、プログラムがまだデバッグ中の場合、これは面倒な作業になる場合があります。今月のEric Allen氏の記事では、プログラム中の式やステートメントを対話式に評価することのメリットについて説明し、そのために役立つJavaのrepl ("read-eval-print-loop" ツール) のいくつかを紹介します。また、GUIを開発したり新しいAPIを探求したりする上で、対話式評価がいかに便利かを示します。この記事を読むことによって、すでにある程度デバッグ済みのプログラムに含まれるバグを対話式に診断する方法を理解することができ、作業に役立つJavaツールのいくつかの入手先を知ることができます。
ほとんどの場合、プログラムにはたくさんのクラス、そしてたくさんのメソッドが含まれています。当然ながら、それらのメソッドのすべてを、プログラムのmainエントリー・ポイントだけからテストするのは、不可能ではないにしても非常に困難です。
その点、単体テストが役立ちます。私自身を含めて多くのプログラマーやソフトウェア設計者は、堅固なソフトウェアを作成する上で単体テストの重要性を強調しています。しかしながら、プログラムのさまざまな要素にもっと対話式にアクセスしたいという場合には、潜在的なトレードオフがあります。
そのような場合、各結果ごとに新しい単体テストを作成し、コンパイルし、実行するのは、なかなか面倒です。特定の入力に対してプログラムがどう動作するかが前もってわからない場合は、特にそうです (AIプログラムなどの場合)。
では、どうすればいいのでしょうか?
小さな変更にこだわらない
1つのアナロジーとして、コンパイル言語 (JavaやC++ など) と、インタープリター言語 (PythonやSchemeなど) の違いについて考慮してみましょう。
コンパイル言語の場合、コーディング/テスト/デバッグのサイクルには、当然のことながらコンパイルという余分のステップが必要であり、小さな変更がたくさんある場合には、うんざりするような作業になりかねません。この点に関しては、インタープリター言語のほうが流動的であり、修正が容易であると言えます。(ただし、柔軟であることには犠牲が伴います。一般にインタープリター言語では、型検査などコードに関する静的検査が貧弱になる傾向があります。)
再コンパイルなしでプログラムに変更を加えたいということ以外にも、新しい単体テストを追加せずにプログラムの特定の要素を検査したいということがあります。そういう場合、伝統的に「read-eval-printループ」(repl) と呼ばれる処理が役立ちます。
repl は、式を入力とし、特定のプログラムのコンテキストの中でそれを評価し、その結果を表示するためのテキスト・ベースのツールです。結果を表示した後は、再び別の式が入力されるのを待機し、処理を繰り返します。その起源はLispに類する言語にありますが、Pythonなど比較的最近の言語でも使用されています。
Javaプログラミングでreplを使用するメリット
そのようなツールを便利に使用できるのは、それらの言語においてだけではありません。Javaプログラマーは、デバッグ以外でもreplを活用できます。
GUI開発においては、レイアウトを決めて接続する必要のあるコンポーネントが数多くあります。GUI開発については、次のように言うことができるでしょう。
- コンポーネントは、自明でない方法で相互に作用します。
- GUIをとにかく実行するためのコードをすべてコーディングするには相当の時間がかかります。
- 実際にそれがどう表示されるかを確認した後、まず間違いなく、そのGUIのさまざまな面を変更したくなります。
この問題に対する一般的な "解決策" は、JBuilderやForteなどのIDEに含まれるような、GUI開発用グラフィック・ツールを使用することです。私は、個人的にはそのようなアプローチが嫌いです。ツールがどんなJavaコードを生成するのかを知ることは困難だし、生成されたコードを修正することはGUI開発ツールとの互換性がなくなるかもしれないという危険を伴うからです (実際IDEによっては、自動生成コードを直接修正することが禁止されています)。
さらに、多くのGUI開発ツールでは、Javaコード生成において独自のGUIライブラリーが使用されており、GUIの互換性の点で制限があります。
GUI開発は、replを使用するほうがずっと簡単です。対話的にGUIコンポーネントを定義し、それを表示すればいいのです。気に入らない点があれば、ただちに修正できます。それから対話的処理を使用して、それらをプログラムに取り込むことができます。
Java言語によるプログラミングの最大の長所の1つは、データベースからWeb Servicesやテレビに至るまで、ありとあらゆるものに接続できる膨大なAPIの資産を活用できることです。しかし、各APIのセマンティクスを習得するには、時間がかかります。
一方、JavadocsがAPIの動作のあらゆる側面を記述し切れていないことがしばしばあります。このジレンマを解決する1つの方法は、APIを直接にテストすることであり、それにはreplを使えば、ずっと短時間で済みます。つまり、単にメソッド呼び出しを入力して、その場でその結果を見ればよいのです!
APIテストにreplを使用する付加的なメリットの1つは、ほとんどのプログラマーの主要な行動パターン、つまり実際にやってみて覚える、という傾向を強化することもできる、ということでしょう。
Javaプログラミングで使用可能なrepl
replにはこれだけのメリットがあるわけですから、次に考えるべき点は、Java言語で使用できるreplには、どんなものがあるか、ということです。
Jython
Jython (以前はJPythonとも呼ばれていた) は、Python (replを含む) を (100%ピュア) Javaプログラミング言語で実装したものです。実際には、JythonはPythonをコンパイルして、(ちょっと独特な) Javaソース・コードに、または直接バイトコードにします。
Pythonの精神として、JavaとJythonとのシームレスなインターオペラビリティーを提供するためのあらゆる努力が払われてきました。あたかもネイティブにJavaでプログラミングしているかのようにJavaの標準ライブラリーのすべてを利用することができ、既存のJavaクラス・ファイルを利用することも可能です。replを使用すれば、標準ライブラリーだけでなく、バイトコードにコンパイルした独自のJava (またはJython) クラスも処理できます。
Jython replを使用する際に、考慮するべき1つの重要な点は、コーディングするのがPythonの式 であって、Javaの式ではないということです。それには、簡潔で美しいPythonの構文を利用できるという積極的な面があります。
たとえば、a を1に、b を2に、そしてc を3に対応させる新しいハッシュ・テーブルを作成するとしましょう。Jythonなら、次のようにコーディングするだけです。
>>> h = {'a':1, 'b':2, 'c':3} |
新しい入力行の前に、インタープリターによって> が表示されます。
Jythonの構文は、新しいGUIのデザインをいろいろ探る場合にも、大きなメリットがあります。1つの点は、GUI要素のさまざまなフィールドを、コンストラクターへのキーワード引き数として指定できるということです。たとえば、
>>> from javax.swing import *
>>> f = JFrame(visible=1)
|
この例は、JythonとJava言語の相違点のいくつかを示しています。
- importステートメントの構文が大きく異なっています。
- ブール値の代わりに整数値が使用されています (1がtrue、0がfalseに対応)。
Jythonコードのほうが入力量が少なくて済むことを示す、別の例を示しましょう。GUI要素にアクション・リスナーを追加するコードです。通常、そのようなリスナーは、Command Patternを使用することにより、無名の内部クラスのインスタンスとして指定します。Python (およびその他の多くのスクリプト言語) では、対話式関数定義を使用することにより、そのようなコマンドを非常に簡潔に指定できます。たとえば、上記の対話式セッションにおいて、シンプルなアクション・リスナーをJButtonに追加してみましょう。
>>> def listener(event):
... print 'thank you'
>>>
|
これは、Jythonでの関数定義の例です。インタープリターが省略記号を表示することで、ステートメントが次の行に続くことを知ることができます。この関数は、引き数が1個であり、"thank you" という文字列を標準出力に出力します。これは、次のようにしてアクション・リスナーとして利用できます。
>>> panel = JPanel()
>>> panel.add(JButton('press me', actionPerformed=listener))
>>> f.getContentPane().add(panel)
>>> f.pack()
|
これで画面にウィンドウが表示され、そこに "press me" というボタンが表示されます。このボタンを押すと、"thank you" という文字列が標準出力に出力されます。Javaコードでこれをコーディングしたら、どれだけのコード量になるかを想像してみてください。
もちろん、デメリットもあります。たとえば、
- 静的型検査の機能は利用できません (静的検査がreplでどれだけ利用価値があるかは疑問ですが)。
- replで入力する式はJavaコードではないので、replからプログラムに、変換なしで式をそのままコピー・アンド・ペーストすることはできません。
- JavaコードでJythonを使用する場合、頭の中で同時に2つの言語で考えることになります (人によっては面白いと感じるかもしれませんが)。
DynamicJava
Javaで使用できるもう1つのreplはDynamicJavaです。これは、本当にJavaベース (まあ、そう言ってよいでしょう) のオープン・ソース・ツールです。これには、若干の相違点があります。
- repl言語では、変数宣言で変数の静的型指定の必要がありません。
- ステートメントの終わりにセミコロンを入力する必要がありません。また、インタープリターは、ステートメントの評価結果として
null を戻します。(ステートメントが値を戻さないよりは、このほうが優れています。)
- replからは、オブジェクトのprivateフィールドへのアクセスに関して制限はありません。
Javaプログラマー初心者にとっては、これらの相違点は混乱の元になるかもしれません。経験を積んだプログラマーであれば、制限が緩くて楽だと感じることでしょう。いずれにしても、DynamicJavaは堅固であり、非常に便利なソフトウェア・プロダクトです (おまけにそれはフリーです)。
 |
新しいJava IDE
Rice大学のJavaPLT研究所は、Robert Cartwright教授の指導で、DrJavaというオープン・ソースの新しいGPLライセンスされた開発環境をリリースしました。これは、Java言語用の開発環境であり、DynamicJava replの "クリーンアップ" バージョンが組み込みコンポーネントとして含まれています。ここで "クリーンアップ" と書いたのは、前述のようなDynamicJavaの制限の緩さが隠されているためです。
DrJavaプロジェクトは、コンピューター・サイエンスの学生に教えるためのフリーで軽いJava IDEを開発するためのエクストリーム・プログラミング・プロジェクトです。そのIDEは学生用に設計されているとはいえ、短時間で開発できる点で、あらゆるレベルの開発者にとって有用です。実際に生成されるコードとプログラマーとを隔ててしまっている一部のIDEとは異なり、DrJavaの背後にある精神は、開発言語に関するプログラマー自身の持つ知識を活用する強力な開発ツールを提供する、ということです。
このIDEの特徴としては、コメントの非常に正確な強調表示 (Emacsを上回る正確さ)、括弧の対応、クリック可能なコンパイラー・エラー・ソース強調表示があります。このインターフェースには、いくつかのクリック可能なタブが含まれています。
- 「Interactions」タブは、DynamicJava replと対話して、新しくコンパイルしたクラスのインスタンスを作成したりテストしたりする場所です。
- 「Compiler Errors」タブには、さまざまなコンパイラー・エラーが表示されます。それをクリックすると、編集パネルの中で、ソース・コードのうちそのエラーに対応する位置にカーソルが移動します。
- 「Console」タブには、
System.out およびSystem.err に送られるすべてのメッセージが表示されます。
(DrJavaの画面ショットをご覧ください。)
このIDEを実際に使用してみて言えることは、「Interactions」ペインを使用することによって、開発やデバッグの高度な作業をプログラマーが簡単に実行できるということです。他の言語と同じように、ソース・エディターとreplを組み合わせると、非常に強力な道具になります。
|
|

 |
replについての結論
今回は、再コンパイルすることなくJavaプログラムの式やステートメントを対話式に評価するためのツール ("read-eval-print-loop"、repl) について紹介しました。また、GUI開発において、また豊富なJava APIを手軽に探求するための手段として、replがいかに重要かを示しました。
参考文献
著者について  | |  | Eric Allen氏は、コーネル大学でコンピューター・サイエンスと数学の学士号を取得しています。現在は、ライス大学の博士課程の大学院生としてJavaプログラミング言語チームに加わっています。学位を終了するためにライス大学に戻るまでは、Cycorp, IncでJavaソフトウェア開発主任として勤務していました。彼は、JavaWorldで「Java Beginner」ディスカッション・フォーラムの司会者も務めています。主な研究対象は、Java言語のセマンティック・モデルと静的分析ツールの開発であり、いずれもソース・レベルとバイトコード・レベルで研究しています。Ericは、NextGenというプログラミング言語 (汎用ランタイム型によるJava言語の拡張版) のためのライスのコンパイラーの開発にも携わってきました。連絡先は、eallen@cs.rice.edu です。 |
記事の評価
|