既存ソフトウェア中の頻出コード片を用いたコード補完手法の提案
Download
Report
Transcript 既存ソフトウェア中の頻出コード片を用いたコード補完手法の提案
コーディングパターンと
キーワードを用いて生成した
コードスニペットの推薦
大阪大学
○関山 太朗,伊達 浩典,石尾 隆,井上 克郎
1
プログラム上のパターン
何度も書かかれた類似したソースコードの断片
ソースコードの断片:コード片,コードスニペット
...for (String s : strs) {
...
}...
...for (Object o : collection) {
...
}...
for ([iterable type]
[iterable element] : [iterable]) {
}
2
開発環境におけるコード補完
キーワードからよく使うコード片を生成
よく使うコード片を素早く利用できる
知らない機能を発見することがある
例: Eclipseのコード補完
“foreach”
キーワードからコレクションの各要素を順に処理
するコード片を生成
foreach
for ([iterable type]
[iterable element] : [iterable]) {
}
Eclipseコード補完の例
3
既存のコード補完の問題
使用できるパターンが限定されている
コード補完の実装であらかじめ用意されている
対象のプログラミング言語でよく使用される
ソフトウェア固有のパターンを用いたコード片の生成を
行うことができない
既存のパターンと類似した処理を再度記述することに
欠陥の混入と開発コストの増大につながる
4
ソフトウェア固有のパターン(1/2)
ソフトウェア固有の機能が含まれているパターン
jEditに頻出するコード片
if (!buffer.isEditable()) {
getToolkit().beep();
return ;
} ...
テキストが編集できなければ
音を鳴らして終了する処理
jEditの機能である編集の可否をチェックする
メソッド isEditable が含まれている
5
ソフトウェア固有のパターン(2/2)
再利用可能だが1つにまとめられないパターンが存在
関数
jEditに頻出するコード片
if (!buffer.isEditable()) {
getToolkit().beep();
return ;
} ...
関数化
void exitUnlessEditable() {
if (!buffer.isEditable()) {
getToolkit().beep();
return ;
}}
関数の適用
exitUnlessEditableメソッドの呼び出し後に
inputCharメソッドの実行を終了できない
void inputChar(char c) {
exitUnlessEditable();
... }
関数適用時のコード片
6
コーディングパターン
我々の研究グループではソフトウェア固有のパターン
を得るための手法を提案してきた[Ishio, 2008]
コーディングパターンとは
ソフトウェアに頻出するコード片
メソッド呼び出しと制御文の開始と終了の列
コーディングパターン
jEditに頻出するコード片
if (!buffer.isEditable()) {
getToolkit().beep();
return ;
} ...
コーディング
パターンの抽出
JEditBuffer.isEditable()
IF
JComponent.getToolkit()
Toolkit.beep()
END-IF
[Ishio, 2008] Ishio, T., Date, H., Miyake, T. and Inoue, K.:Mining Coding Patterns to Detect Crosscutting Concerns
in Java Programs. Inproceedings of 15th Working Conference on Reverse Engineering, pp.123-132 (2008).
7
提案手法
既存のコード補完の問題点を解決
ソフトウェア固有のパターンと類似した処理を再度記述する
ことを防ぐ
コーディングパターンに基づくコード補完手法の提案
ソフトウェア固有のパターンはコーディングパターンとして得
られる
8
提案手法:
コーディングパターンに基づくコード補完手法
開発者が入力
した単語(キーワード)
1.パターンの検索
パターン
データベース
開発者が編集して
いるソースコード
2.コード片の生成
キーワードに
関連したパターン
3.ソースコード
へ挿入
パターンから
生成したコード片
9
パターンデータベースの構築
コーディングパターンの取得には既存手法を使用
コーディングパターンを保存したデータベースをパター
ン検索の前に構築
コーディングパターン
jEditに頻出するコード片
if (!buffer.isEditable()) {
getToolkit().beep();
return ;
} ...
コーディング
パターンの抽出
JEditBuffer.isEditable()
IF
JComponent.getToolkit()
Toolkit.beep()
END-IF
10
パターンの検索
入力キーワードに関連したパターン
パターンに入力キーワードと一致する単語が多く出現
一致する単語のうち,重みの大きい単語が多い
単語の重みは自然言語検索で利用されているTF-IDF[Salton,1987]
で決定
検索結果:
入力キーワードに最も関連している k 個のパターン
実装したツールでは
k=3
[Salton,1987] Term Frequency – Inverse Document Frequency,
Salton G. and Buckley, C. 1987 Term Weighting Approaches in Automatic Text Retrieval. Technical Report.
UMI Order Number: TR87-881., Cornell University.
11
コード片の生成: パターン要素の変換
パターンの各要素をコード片へ変換
このステップでは参照する変数は未定とする
コード片
パターン
JEditBuffer.isEditable()
???.isEditable();
IF
if (???) {
JComponent.getToolkit()
???.getToolkit();
Toolkit.beep()
???.beep();
END-IF
}
12
コード片の生成: 参照変数の決定
挿入箇所の直前で宣言した変数を使用
メソッド呼び出しの戻り値は新しく宣言した変数へ代入
編集中のソースコード
JEditBuffer buf = ...;
コード片
???.isEditable();
if (???) {
???.getToolkit();
???.beep();
}
ソースコードへ挿入
するコード片
boolean var0 = buf.isEditable();
if (var0) {
JComponent var1;
Toolkit var2 = var1.getToolkit();
var2.beep();
}
13
ソースコードへの挿入
生成したコード片を開発者が編集しているソースコー
ドへ挿入
挿入後のソースコードを開発者へ提示
開発者は必要に応じて提示されたソースコードを編集
14
実装: Eclipseプラグイン
コード片
入力キーワード
15
実験: 妥当性の検証
パターンの検索
2. コード片の生成
1.
開発者が入力
した単語(キーワード)
1.パターンの検索
パターン
データベース
開発者が編集して
いるソースコード
2.コード片の生成
キーワードに
関連したパターン
3.ソースコード
へ挿入
パターンから
生成したコード片
16
妥当性の検証: パターンの検索
対象
方法
Pa: jEdit4.3から取得したパターン集合
Pb: Paのうち重みの大きい単語が出現するパターン集合
パターン自身に出現する単語をキーワードとして検索し,順位を調査
結果
パターンが上位3位以内に含まれる確率
Pa: 0.4371
Pb: 0.9775
考察
目的のパターンを得るためには複数回の検索が必要な場合もある
実装ツールでは1回の実行時間は約1秒
17
妥当性の検証: コード片の生成
対象
jEdit4.3のパターンからランダムに選んだ11個のパターン
パターンの総数: 7559
方法
1.
2.
3.
パターンが出現する既存ソースコードを1つ選び,削除
パターンと削除後のソースコードからコード片を生成
削除した部分と生成したコード片の変数の使用方法を比較
...;
if (!buffer.isEditable()) {
getToolkit().beep();
}
...;
...;
コード片の生成・置換
生成したコード片
比較
...;
18
妥当性の検証結果(1/2): コード片の生成
変数の使用方法が
一致するケース
変数の使用方法が
異なるケース
7
4
変数名のrename
変数の初期化
変数の使用方法が一致するケース
boolean var0;
{
StringTokenizer st = ...;
while (...) {
String keyCodeStr =
st.nextToken();
...
... (st.hasMoreTokens()) ...
}
while (var0) {
java.lang.String var1 =
st.nextToken();
boolean var2 =
st.hasMoreTokens();
}
既存のソースコード
}
生成したコード片
19
妥当性の検証結果(2/2): コード片の生成
変数の使用方法が異なるパターンの特徴
GUIの設定
同じ型の引数を複数とるメソッド呼び出しが出現
基本データ型が出現
int 型など
int caret, newCaret; ...
{
if (...)
this.extendSelection(caret,
newCaret);
else { ...
this.selectNone();
}
} ...
boolean var0;
if (var0) {
this.extendSelection(newCaret,
newCaret);
} else {
this.selectNone();
}
同じ型の引数を複数とるメソッド呼び出しが出現する例
20
考察: コード片の生成
変数の使用方法が一致した理由
パターンの要素間にはコード片がほとんど含まれない
同一の型が同時に使用されることはほとんどない
例外: GUIで使用するクラスや基本型など
変数の使用方法が異なるケースの解決案
パターンが出現するソースコードの利用
データフロー情報
21
まとめと今後の課題
まとめ
コーディングパターンに基づくコード補完手法を提案
提案手法に対する評価実験を行い,次の妥当性を検証
パターンの検索
コード片の生成
今後の課題
データフロー情報を利用したコード片の生成
実際のソフトウェア開発における評価
22