プログラムの差分記述を 容易に行うための レイヤー機構付きIDEの提案 数理・計算科学専攻 09M37287 松本 久志 指導教員 千葉 滋
プログラムの差分記述 既存のプログラムに対して差分を記述することで 新しいプログラムの開発を行う 仕様の類似したソフトウェアの開発 既存のプログラムに対して差分を記述することで 新しいプログラムの開発を行う 仕様の類似したソフトウェアの開発 組み込みソフトウェア開発 パッケージソフトウェアの複数エディション フリーソフト版とシェアウェア版の差別化 デバッグ用コードの挿入・除去 まず、タイトルにあるプログラムの差分記述について説明します。 これは、既存の~ といった開発手法を指しています。 このような差分記述は、仕様の類似したソフトウェアの開発、たとえば、 組み込み~・・・ のような場合に有効です。 また、もっと身近な例としては、デバッグ用コードの挿入などが挙げられます。
#ifdef/#endifによる差分記述 C/C++のプリプロセス命令 #defineにより差分記述が可能 ソースコード中に直接記述 行単位での任意の差分記述が可能 問題点 可読性の低下 コード変更の必要性 ある差分に関連するコードの抽出が困難 他の言語への導入が困難 構文解析器の拡張が必要 #define SYNC // #define LOG static void run() { Hoge h = new Hoge(); #ifdef SYNC synchronized(lock) { #endif #ifdef LOG System.out.println(“run”); h.run(); } このような差分記述を行うための手法としては、 C/C++の#ifdef/#endifディレクティブを利用する方法が考えられます。 これらの理由から#ifdef/#endifは、差分記述を行うための支援としては不十分であると考えられます。 Javaに#ifdef/#endifを 導入した仮想言語
求められる支援 差分を自由にon/off可能 ある差分に関連するコードをまとめて扱う 既存のIDEの拡張が容易 コンパイル時の適用・非適用 編集時の表示・非表示 コードを変更しない ある差分に関連するコードをまとめて扱う 関連コードの抽出 リファクタリング 既存のIDEの拡張が容易 既存のエディターやコンパイラを流用 そのため本研究では、差分記述の支援としてこのようなものが必要であると考えました。
提案:レイヤー機構付きIDE レイヤーとは 差分に関連するソースコード断片 IDE上でまとめて操作可能 #define SYNC // #define LOG static void run() { Hoge h = new Hoge(); #ifdef SYNC synchronized(lock) { #endif #ifdef LOG System.out.println(“run”); h.run(); } レイヤーとは 差分に関連するソースコード断片 IDE上でまとめて操作可能 レイヤーごとの表示・非表示(エディター) レイヤーごとの適用・非適用(コンパイラ) ベースとなるプログラム ログ出力に関するコード 同期に関するコード static void run() { Hoge h = new Hoge(); h.run(); } System.out.print(“run”); synchronized(lock) { }
レイヤーのファイル上での表現 ソースファイル内ではプリプロセス命令により注釈 レイヤーの選択状況と併せてIDEが解釈 解釈されたソースコード レイヤーの 選択状況 static void run() { Hoge h = new Hoge(); #ifdef SYNC synchronized(lock) { #endif #ifdef LOG System.out.println(“run”); h.run(); } static void run() { Hoge h = new Hoge(); h.run(); } synchronized(lock) { } ○ ベースレイヤー × ログレイヤー ○ 同期レイヤー
IDEの提供する操作 (1/2) レイヤーのon/offの切り替え エディター上での表示・非表示 コンパイル時の適用・非適用 static void run() { Hoge h = new Hoge(); synchronized(lock) { System.out.print(“run”); h.run(); } static void run() { Hoge h = new Hoge(); synchronized(lock) { h.run(); } static void run() { Hoge h = new Hoge(); h.run(); } ログ・同期両方の レイヤーを適用 ログレイヤーのみ適用 ログ・同期両方の レイヤーを非適用
IDEの提供する操作 (2/2) 指定したレイヤーの着色 背景色を変更 差分に関連するコードを視覚的に抽出可能 static void run() { Hoge h = new Hoge(); synchronized(lock) { System.out.print(“run”); h.run(); } static void run() { Hoge h = new Hoge(); synchronized(lock) { System.out.print(“run”); h.run(); } static void run() { Hoge h = new Hoge(); synchronized(lock) { System.out.print(“run”); h.run(); } ベースレイヤーを選択 ログレイヤーを選択 同期レイヤーを選択
IDE内部の処理 ソースコードをプリプロセッサにより変換 変換したコードをエディターやコンパイラへ 既存のエディターやコンパイラを流用可能
実装:LayerIDE 対象言語 Eclipseプラグイン Java + #ifdef/#endif ビュー エディター ビルダー レイヤーの操作 エディター プリプロセス命令を解釈して表示 ビルダー プリプロセス命令を解釈してコンパイル
ビュー レイヤーの操作を統括して行う レイヤー状態の変化を通知 レイヤーの表示 レイヤーの作成・削除・統合 レイヤーのon/off 着色するレイヤーの選択 レイヤー状態の変化を通知 エディターの表示を変更 自動および手動でコンパイル
エディター レイヤー状態を反映して表示 コードの折りたたみによりコードの非表示を表現 プリプロセス命令は灰色で表示 差分の存在を示す 可読性の低下を防ぐ
ビルダー クラスファイルの生成 自動ビルド プリプロセッサ処理後JDTのコンパイラに処理を委譲 ソースファイルの保存時 レイヤー構成の変更時 既存のコンパイラの流用
デモ LayerIDEを用いて差分記述を行った GUI・CUIの切り替え コア部分およびGUI・CUI・LOGの3つのレイヤーで構成 ぷよぷよ(パズルゲーム)の連鎖シミュレーター コア部分およびGUI・CUI・LOGの3つのレイヤーで構成 引数からフィールドを生成し、 連鎖をシミュレート 状態などのログを出力 LOG差分 コア部分 シミュレートした連鎖を グラフィカルに表示 シミュレートした連鎖を コンソールに表示 GUI差分 CUI差分
LayerIDE内部の処理 ファイルの読み込み後に変換 エディターは新たに作成 ビルダーは流用可能 想定していた実装 実際の実装 拡張ポイントによる 処理の追加が困難
関連研究 AspectJ [Kiczalesら ‘2001] Colored IDE [Kästner ら ‘2008] アスペクト指向言語 横断的関心事をモジュール化 差分を横断的関心事として捉える メソッド単位より細かい粒度の改変が困難 コンパイラの拡張が必要 Colored IDE [Kästner ら ‘2008] Eclipseプラグイン ASTに対してFeatureを関連付ける エディタ上では色を付けて表示 言語に依存する 完全な形のASTが存在する必要がある
まとめ レイヤー機構付きIDEの提案 LayerIDEの実装 レイヤーとは IDE上で差分を操作可能 Eclipseプラグイン 編集時の表示・非表示 コンパイル時の適用・非適用 レイヤーの着色 LayerIDEの実装 Eclipseプラグイン Java + #ifdef/#endif