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