タイトル

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