○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学

Slides:



Advertisements
Similar presentations
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 1 ソフトウェア部品推薦のための.
Advertisements

Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 保守支援を目的とした コードクローン情報検索ツール.
背景 ソフトウェアの大規模化・複雑化 生産性と品質の向上 ↓ オブジェクト指向分析設計の適用 開発ツールの投入.
XHTML構文検証手法における スクリプト要素の静的解析アルゴリズム
メソッド周辺の識別子と メソッド本体のAPI利用実績に基づいたAPI集合推薦手法
変数間データフローグラフを用いた ソースコード間の移動支援
リファクタリングのための 変更波及解析を利用した テスト支援ツールの提案
メソッド名とその周辺の識別子の 相関ルールに基づくメソッド名変更支援手法
川口真司 松下誠 井上克郎 大阪大学大学院情報科学研究科
ソースコードに対する適用可能な修正手順を 可視化するリファクタリング支援手法の提案
プログラム実行履歴を用いたトランザクションファンクション抽出手法
ソースコードの変更履歴における メトリクス値の変化を用いた ソフトウェアの特性分析
ギャップを含むコードクローンの フィルタリング手法の提案
同一メソッド内に含まれる ブロック間の結合度を用いた メソッド分割手法の提案
類似するコーディングパターンの 利用状況調査ツールの提案
コードクローンに含まれるメソッド呼び出しの 変更度合の分析
コードクローンに含まれるメソッド呼び出しの 変更度合の調査
識別子の命名支援を目的とした動詞-目的語関係の辞書構築
識別子の共起関係に基づく類似コード検索法の提案と 欠陥検出への適用
ソードコードの編集に基づいた コードクローンの分類とその分析システム
コードクローンの分類に基づいた メソッド引き上げ手順の提案とその有効性評価
リファクタリング中に生じる コンパイルエラーの自動解消手法
動的依存グラフの3-gramを用いた 実行トレースの比較手法
オブジェクト指向プログラムにおける エイリアス解析手法の提案と実現
動的スライスを用いたバグ修正前後の実行系列の差分検出手法
利用関係に基づく類似度を用いたJavaコンポーネント分類ツールの作成
クローンセットに対する主要編集者の分析法の提案と調査
Javaプログラムの変更を支援する 影響波及解析システム
コードクローン検出ツールを用いた ソースコード分析システムの試作と プログラミング演習への適用
リファクタリング支援のための コードクローンに含まれる識別子の対応関係分析
ソースコードの特徴量を用いた機械学習による メソッド抽出リファクタリング推薦手法
オープンソース開発支援のための リビジョン情報と電子メールの検索システム
コードクローンの動作を比較するためのコードクローン周辺コードの解析
UMLモデルを対象とした リファクタリング候補検出の試み
コードクローン検出に基づくデザイン パターン適用支援手法の提案と実現
プログラムで多用される 動詞と目的語の関係を利用した メソッド名提案ツール
プログラム理解におけるThin sliceの 統計的調査による有用性評価
バイトコードを単位とするJavaスライスシステムの試作
コード片に共通した特性を自動抽出する ソースコード閲覧ツールの試作
Javaソフトウェア部品検索システムSPARS-Jの実験的評価
ソフトウェア保守のための コードクローン情報検索ツール
コードクローンの理解支援を目的としたコードクローン周辺コードの解析
コードクローン分類の詳細化に基づく 集約パターンの提案と評価
コーディングパターンの あいまい検索の提案と実装
JAVAバイトコードにおける データ依存解析手法の提案と実装
JavaScriptを含んだHTML文書に対する データフロー解析を用いた構文検証手法の提案
コードクローン間の依存関係に基づく リファクタリング支援環境の実装
ソフトウェアプロダクト集合に対する 派生関係木の構築
プログラムスライスを用いた凝集度メトリクスに基づく 類似メソッド集約候補の順位付け手法
設計情報の再利用を目的とした UML図の自動推薦ツール
依存関係の局所性を利用した プログラム依存グラフの 効率的な構築法
保守請負時を対象とした 労力見積のためのメトリクスの提案
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
プログラムの差分記述を 容易に行うための レイヤー機構付きIDEの提案
クローン検出ツールを用いた ソフトウェアシステムの類似度調査
オープンソースソフトウェアに対する コーディングパターン分析の適用
メソッドの同時更新履歴を用いたクラスの機能別分類法
プログラム依存グラフの一貫性検査に基づく欠陥候補の検出手法
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
統合開発環境のための プログラミング言語拡張 フレームワーク
欠陥検出を目的とした類似コード検索法 吉田則裕,石尾隆,松下誠,井上克郎 大阪大学 大学院情報科学研究科
エイリアス関係を考慮した Javaプログラム用静的スライシングツール
プログラムの一時停止時に 将来の実行情報を提供するデバッガ
コードクローン解析に基づく デザインパターン適用候補の検出手法
メソッド抽出リファクタリングが 行われるメソッドの特徴調査
オブジェクト指向メトリクスを用いた 開発支援に関する研究 --- VC++とMFCを用いた開発を対象として ---
プログラム理解のための 付加注釈 DocumentTag の提案
プログラム依存グラフを用いた ソースコードのパターン違反検出法
Detecting Software Modularity Violations
Presentation transcript:

○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学 差分を含む類似メソッドの集約支援ツール ○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学

研究概要 類似メソッドの集約作業を支援する手法を提案 手法を統合開発環境のプラグインとして実装 オープンソース上の類似メソッドに手法を適用 抽象構文木を用いて集約候補を検出 集約候補を凝集度の高い順に並び替えて提示 手法を統合開発環境のプラグインとして実装 オープンソース上の類似メソッドに手法を適用 アンケートによって集約候補を評価 有用な集約候補を提示できていることを確認

類似メソッド 互いに一致または類似したメソッド ソフトウェアの保守性を低下させる要因 欠陥 同様の欠陥が存在する可能性が高い ・・・ 類似メソッド 同様の欠陥が存在する可能性が高い

類似メソッドの集約 類似メソッドをまとめて1つのメソッドにする 類似メソッドに差分が存在する場合 差分をメソッドとして抽出して,類似メソッドを完全一致させる 集約

類似メソッド集約手順(1/3) 類似メソッド間の差分を特定する public void similarMethodA(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.putLong(length << 3); public void similarMethodB(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.putLong(length << 3); ・ ・ ・ ・

条件1:全てのコード片はメソッド抽出可能である 類似メソッド集約手順(2/3) メソッドとして抽出するコード片の集合を決定する public void similarMethodA(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.putLong(length << 3); public void similarMethodB(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.putLong(length << 3); 条件1:全てのコード片はメソッド抽出可能である ・ ・ ・ ・

条件2:同じメソッド内の各コード片は重複部分がない 類似メソッド集約手順(2/3) メソッドとして抽出するコード片の集合を決定する public void similarMethodA(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.putLong(length << 3); public void similarMethodB(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.putLong(length << 3); 条件2:同じメソッド内の各コード片は重複部分がない ・ ・ ・ ・

条件3:各差分はいずれかのコード片に含まれる 類似メソッド集約手順(2/3) メソッドとして抽出するコード片の集合を決定する public void similarMethodA(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.putLong(length << 3); public void similarMethodB(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.putLong(length << 3); 条件3:各差分はいずれかのコード片に含まれる ・ ・ ・ ・

条件4:抽出後に類似メソッドが完全に一致する 類似メソッド集約手順(2/3) メソッドとして抽出するコード片の集合を決定する public void similarMethodA(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.putLong(length << 3); public void similarMethodB(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.putLong(length << 3); 条件4:抽出後に類似メソッドが完全に一致する ・ ・ ・ ・

類似メソッド集約手順(3/3) 各コード片をメソッドとして抽出する public void similarMethodA(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } methodA(); methodB(); public void similarMethodB(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } methodA(); methodB(); ・ ・ ・ ・

集約作業における問題点 問題点1 : 条件を満たすコード片の集合を,どのように探すか 問題点2 : 条件を満たすコード片の集合のうち,どれを選択するか

提案手法 集約候補を提示することで集約作業を支援 凝集度を用いて集約候補の並び替えを行う 集約候補:メソッドとして抽出するコード片の集合 条件を満たすコード片の集合を提示する 凝集度を用いて集約候補の並び替えを行う 凝集度の高いメソッドは保守性や可読性に優れている 凝集度の高い集約候補を先に提示する

集約候補の例 メソッドとして抽出するコード片の集合 public void similarMethodA(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); finalBuffer.putLong(length << 3); public void similarMethodB(){ if(finalBuffer.remaining() < 8){ while(finalBuffer.remaining() > 0){ finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0); finalBuffer.putLong(length << 3); ・ ・ ・ ・ 12

提案手法の概要 開発者 差分を含む類似メソッド 順位づけされた 集約候補一覧 提案するツール 1. 類似メソッド間の差分を特定する 差分となっているコード片の集合 入力 2. 集約候補を検出する 出力 類似メソッド対の集約候補 1 2 3 ・・・ 3. 凝集度を用いて集約候補を並び替える 順位づけされた 集約候補一覧

1.類似メソッド間の差分の特定 差分を含む類似メソッド 1-1 抽象構文木の比較 1-2 差分を含む文の特定 1-1 抽象構文木の比較 1. 類似メソッド間の差分を特定する 1-2 差分を含む文の特定 差分となっているコード片の集合 1-3 差分の統合

抽象構文木(AST) 各ノードはラベルを持つ(タイプや値を表す) ASTにおける特殊ノードを定義する ソースコード中で1つの文を表すノード Method Declaration int max(int a, int b){ int max = a; if(b > max) max = b; return max; } VariableDeclaration Statement IfStatement ReturnStatement Infix Expression Expression Statement int max = a max 特殊ノード b > max max = b

1-1 ASTの比較 根ノードから葉に向かって再帰的に比較 ノードのラベルを比較して異なっていれば差分とする 比較 差分となっているノード Block Block 比較 Expression Statement Expression Statement Expression Statement Expression Statement a = b b = c a = b b = d 差分となっているノード

1-2 差分を含む文の特定 AST上の差分であるノードから親ノードへ辿っていく 最初に到達した特殊ノードを根とする部分木が差分となっている文に対応している Block Block Expression Statement Expression Statement Expression Statement Expression Statement a = b b = c a = b b = d a = b; b = c; a = b; b = d; ・ ・ ・ ・

1-3 差分の統合 1.隣接している差分の統合 2.中括弧で囲まれたブロック内の差分の統合 これまでの操作で差分となっている文が検出される 隣接している差分の統合を行う 最終的に検出される差分の数を減らすため 1.隣接している差分の統合 2.中括弧で囲まれたブロック内の差分の統合

2.集約候補の検出 差分となっているコード片の集合 2-1 メソッド抽出可能な コード片の検出 2-2 集約候補の検出 2.集約候補の検出 2-3 集約候補のフィルタリング 集約候補一覧

2-1 メソッド抽出可能なコード片の検出 拡大 メソッド抽出可能か判定 差分を含み抽出可能なコード片を全て検出する コード片の拡大とメソッド抽出可能であるかの判定を繰り返し行う if(finalBuffer.remaining() < 8) { while(finalBuffer.remaining() > 0) { finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer); 拡大 メソッド抽出可能か判定

2-2 集約候補の検出 差分δ1 差分δ2 条件を満たすように コード片を選択する 差分δ1を含みメソッド抽出可能な コード片の集合 if(finalBuffer.remaining() < 8) { while(finalBuffer.remaining() > 0) { finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer);  finalBuffer.putLong(length << 3); 差分δ1 条件を満たすように コード片を選択する 差分δ2 差分δ2を含みメソッド抽出可能な コード片の集合

2-3 集約候補のフィルタリング 広い範囲をメソッドとして抽出する集約候補は除外 抽出後のメソッドが再び類似メソッドとなる if(finalBuffer.remaining() < 8) { while(finalBuffer.remaining() > 0) { finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer);  finalBuffer.putLong(length << 3); if(finalBuffer.remaining() < 8) { while(finalBuffer.remaining() > 0) { finalBuffer.put((byte)0); } finalBuffer.position(0); transform(finalBuffer.array(),0);  finalBuffer.putLong(length << 3); 抽出範囲が広すぎる

3. 集約候補の並び替え 開発者は提示された候補の中から1つを選択する 凝集度が高い集約候補から順番に提示する 集約候補の数が多い場合,選択する作業が困難になる 凝集度が高い集約候補から順番に提示する 凝集度の高いメソッドは保守性や可読性に優れている 1 2 3 4 ・・・ 凝集度が高い良い候補

凝集度メトリクス プログラムスライスを用いた凝集度メトリクス [1] 提案手法ではメソッドの引数も使用する 3種類のメトリクスを使用 メソッドの返り値に着目して凝集度を計測 提案手法ではメソッドの引数も使用する 返り値が存在しないメソッドの凝集度を計算するため 3種類のメトリクスを使用 FTightness, FCoverage, FOverlap それぞれ独立に使用して3つのランキングを生成する [1] Weiser, M.: Program slicing, Proc. of ICSE1981, pp.439–449 (1981)

凝集度の計算例 FTightness = 0.500 FCoverage = 0.722 FOverlap = 0.750 積集合に含まれる文の数 メソッドの文の数 積集合に含まれる文の数 各スライスに含まれる文の数 各スライスに含まれる文の数 メソッドの文の数 全スライスの積集合 引数 a,b を起点とした 前向きスライス | SLa | SLb | SLresult | SLint int permutation(int a, int b) { int i; int result = 1; for (i = 0; i < b; i++) { result = result * a; a = a – 1; } return result; 1 2 3 4 5 6 7 8 9 FTightness = 0.500 FCoverage = 0.722 返り値 result を起点とした 後ろ向きスライス FOverlap = 0.750

実装 提案手法を Eclipse プラグインとして実装 集約候補の選択タブ(番号は検出順) 集約候補中のコード片 メトリクスの選択

適用実験 オープンソース上の類似メソッドに手法を適用 出力結果に対して評価アンケートを実施 アンケート内容 被験者が良いと思う候補を提示できているか 被験者は学生15名(ソフトウェア工学関連の研究室に所属) アンケート内容 出力された候補のうち,上位10候補を被験者へ提示 提示された候補のうち良いと思う候補を選択 (複数可)

実験対象 Ant プロジェクト executeDrawOperation メソッド Arc クラス, Ellipse クラス ANTLR プロジェクト genErrorHandler メソッド CppCodeGenerator クラス, JavaCodeGenerator クラス フィルタリングの閾値を0.5に設定して手法を適用 Ant :14 個の集約候補を検出(フィルタリング前は23個) ANTLR : 6 個の集約候補を検出(フィルタリング前は34個)

評価尺度(1/2) 平均候補選択率 平均候補選択率 = 全体のうち被験者に選択された集約候補の割合 選択された候補数 提示した全候補数 被験者にとって有用な集約候補がどれだけ存在するか 選択された候補数 平均候補選択率 = 提示した全候補数

評価尺度(2/2) 平均適合率 平均適合率 = 検索エンジンなどのランキングを評価する尺度 [2] 被験者に選択された集約候補が上位に提示されていたか 平均適合率 = :正解集合 :   中の  番目の要素がランキングに現れた時の適合率 [2] Baeza-Yates, R. et al. : Modern Information Retrieval, Addison Wesley, second edition,2011.

平均適合率の計算例 平均値を計算 平均適合率 = 0.532 順位 候補 選択 1 A 2 B ○ 3 C 4 D 5 E 6 F 7 G 8 H 9 I 10 J 全体の候補数:2 選択された候補数:1 適合率 = 0.5 平均値を計算 全体の候補数:3 選択された候補数:2 適合率 = 0.667 平均適合率 = 0.532 全体の候補数:7 選択された候補数:3 適合率 = 0.429

結果(1/2) 平均適合率の結果は 全体の2割程度が被験者に選択されている Ant で約0.5,ANTLR で約0.4 メトリクス 平均候補選択率 平均適合率 Ant FTightness 0.253 0.533 FCoverage 0.213 0.560 FOverlap 0.535 ANTLR 0.267 0.438 0.346 全体の2割程度が被験者に選択されている 平均適合率の結果は Ant で約0.5,ANTLR で約0.4

結果(2/2) Ant に対する FTightness の結果 1位 2位 3位 4位 5位 6位 7位 8位 9位 10位 被験者A ○ 被験者B 被験者C 被験者D 被験者E 被験者F 被験者G 被験者H 被験者I 被験者J 被験者K 被験者L 被験者M 被験者N 被験者O

まとめ 類似メソッドの集約作業を支援する手法を提案 実際の類似メソッドへの適用・アンケート評価 ASTを用いた集約候補の検出 凝集度を用いた集約候補の並び替え 実際の類似メソッドへの適用・アンケート評価 提示した候補のうち,2割程度が有用な候補であった

今後の課題 多数の類似メソッドを対象とした適用実験 ツールへの機能追加 ツールを使用した評価 3つ以上の類似メソッドへの適用 集約候補の検索機能 ツールを使用した評価 集約作業の支援にどの程度有効であるか