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