Download presentation
Presentation is loading. Please wait.
1
ソフトウェアメトリクスと メソッド内の構造を用いた リファクタリング支援手法の提案
大阪大学 M2 三宅達也
2
研究概要 リファクタリングプロセスの一部を自動化する手法の提案 ⇒ 効率的かつ適切なリファクタリングを支援 ソフトウェアメトリクス
メソッド内の構造 変数の宣言、参照位置 ⇒ 効率的かつ適切なリファクタリングを支援 SIGSS
3
発表の流れ 背景 提案手法 評価実験 関連研究 まとめと今後の課題 SIGSS
4
リファクタリング リファクタリングとは? リファクタリングの効果は? ソフトウェアの外部的振る舞いを保ったまま,内部の構造を改善する技術
ソフトウェアの保守性が増し,後の保守作業効率が向上する SIGSS
5
リファクタリングプロセス Step 1: リファクタリングを適用すべきコード(Bad Smell)を特定
長すぎるメソッド 複雑な制御構造 Step 2: どのようなリファクタリングを適用すべきかを決定 既存の研究で様々なリファクタリングパターンが提案 Step 3: 適用するリファクタリングの効果を予測 Step 4: プログラムの修正 Step 5: 修正されたプログラムが正しく動作するかテスト SIGSS
6
リファクタリングの問題点と本研究の目的 手動リファクタリングの問題点 研究目的
Bad Smellの特定や適用すべきリファクタリングパターンの決定には豊富な知識と経験が必要 時間と手間が大きい 誤りが混入しやすい 研究目的 リファクタリングプロセスの一部を自動化し、リファクタリングのコストを削減するための手法を提案 SIGSS
7
提案手法の概要 リファクタリングすべきコードを検出 適用すべきリファクタリングパターンを特定 リファクタリングの効果を測定
検出対象 : メソッド内のコードの一部 複雑度メトリクスの高い部分 同一の機能に関連する範囲を識別 適用すべきリファクタリングパターンを特定 変数やメソッドの利用状況から特定 Extract Method Move Method Pull Up Method リファクタリングの効果を測定 複雑度メトリクスの変化で評価 SIGSS
8
メソッド抽出リファクタリング メソッドの一部を新しいメソッドとして抽出 普遍的で頻繁に行われるリファクタリングパターン
対象 長すぎるメソッド 複雑な制御構造をもつメソッド 効果 再利用性の向上 適切な命名を行うことで内部の処理の可読性が向上 拡張性の向上 普遍的で頻繁に行われるリファクタリングパターン ⇒自動化の効果が大きい 再利用性の向上 ↓ 重複コード生成の防止 開発コストの削減 可読性のコード メソッドが何をしているのかメソッド名のみでわかる 呼び出し側のメソッドをコメント列のようによめる SIGSS
9
提案手法の概要 リファクタリングすべきコードを検出 適用すべきリファクタリングパターンを特定 リファクタリングの効果を測定
検出対象 : メソッド内のコードの一部 複雑度メトリクスの高い部分 同一の機能に関連する範囲を識別 適用すべきリファクタリングパターンを特定 変数やメソッドの利用状況から特定 Extract Method Move Method Pull Up Method リファクタリングの効果を測定 複雑度メトリクスの変化で評価 SIGSS
10
複雑度メトリクスを用いたBad Smellの検出
メソッド単位だけでなく,ブロック分単位で計測 メトリクス値の悪いブロック分を検出 複雑度を測る際に利用するメトリクス サイクロマチック数 値が大きいほど制御構造が複雑 制御文の条件式の数 + 1 LOC(Lines Of Code) メソッド内の占有率 LVA(Local Variable Availability) SIGSS
11
ローカル変数のカプセル化 ⇒ 使用しない変数へのアクセスを制限 他クラスで使用しない属性を隠蔽することによって保守性を向上
フィールドをprivate宣言 必要なフィールドに対してのみアクセサメソッドを作成 フィールドのカプセル化 メソッドの場合も、使用しないローカル変数を隠蔽すれば保守性の向上が見込める メソッドの一部を新規メソッドとして抽出 必要なローカル変数のみ引数や返り値を利用してアクセス ローカル変数のカプセル化 ⇒ 使用しない変数へのアクセスを制限 SIGSS
12
ローカル変数のカプセル化の例 int drawText(Graphics g, int x, int y, int p0, int p1) { int returnVal = super.drawText(g, x, y, p0, p1); String token = null; int toknePos = p0; String buffer = getDocument.getText(p0, p1); LangHighlight lang = getLangHighlight(); StringTokenizer tokens = null; if(lang== LangHighlight.JAVA) toknes = new StringTokenizer(buffer, “…”, true); else if(lang == LangHighlight.COBOL) tokens = new StringTokenizer(buffer, “…”, true); else ・ (省略) return returnVal; } int drawText(Graphics g, int x, int y, int p0, int p1) { int returnVal = super.drawText(g, x, y, p0, p1); String token = null; int toknePos = p0; String buffer = getDocument.getText(p0, p1); StringTokenizer tokens = getTokens(buffer); ・ (省略) return returnVal; } StringTokenizer getTokens(String buffer) { LangHighlight lang = getLangHighlight(); StringTokenizer tokens; if(lang== LangHighlight.JAVA) toknes = new StringTokenizer(buffer, “…”, true); else if(lang == LangHighlight.COBOL) tokens = new StringTokenizer(buffer, “…”, true); else return tokens; drawText内の変数に 返り値を利用して代入 drawText内の変数は 引数として参照 可視変数数:10, 使用変数数:3 メソッドdrawText内で可視な変数の数: 9 可視変数数:3, 使用変数数:3 (可視であった変数の7/10が不可視) メソッド抽出 メソッドdrawText内で可視な変数の数: 10 SIGSS
13
提案手法の概要 リファクタリングすべきコードを検出 適用すべきリファクタリングパターンを特定 リファクタリングの効果を測定
検出対象 : メソッド内のコードの一部 複雑度メトリクスの高い部分 同一の機能に関連する範囲を識別 適用すべきリファクタリングパターンを特定 変数やメソッドの利用状況から特定 Extract Method Move Method Pull Up Method リファクタリングの効果を測定 複雑度メトリクスの変化で評価 SIGSS
14
変数を用いた機能の抽象化 メソッドの機能:コード内に現れる変数の値を決定する計算 ⇒メソッドMの機能をF(M)とすると
コード内の特定の機能はその機能に対応する変数で表すことができる[1] ⇒メソッドMの機能をF(M)とすると [1]丸山.基本ブロックスライシングを用いたメソッド抽出リファクタリング. 情報処理学会論文誌43(6): , Jun 2002. SIGSS
15
変数を用いた機能の抽象化例 void METHOD() { VAR v1, v2, v3; …………………………… BLOCK1 {
} BLOCK3 { v5 = v1 + 4; v5 = v1 + v2 SIGSS
16
抽象化された2つの機能の類似度 共通要素が小さいほうの機能を占める割合 類似度が高いとき2つの機能は同一の機能である可能性が高い
1つのメソッドにまとめるべき 共通要素の数 小さいほうの機能の要素数 SIGSS
17
垂直の関係と水平の関係とは 垂直の関係 水平の関係 sample ( ) while while if for if
public void sample ( ) { int i = 0; String str; while( hoge() ) { str = “string”; if( jar( I ) ) { make(str); } foo(i); for( int j = 0; j < I ; j++) { sam( i ); if( log ) { System.out.println(i); ・ while( ) { bar(i); sample ( ) while while if for 水平の関係 垂直の関係 if SIGSS
18
ブロック文の水平結合 水平の関係にあるブロック文間の結合度 水平結合度が閾値以上 水平の関係にあるブロック文の機能の類似度
B1とB2が水平の関係にある時 水平結合度が閾値以上 2つのブロック文は1つのメソッドとして抽出すべき SIGSS
19
ブロック文の垂直結合 垂直の関係にあるブロック文間の結合度 垂直結合度が閾値以上
内側のブロック文 の機能と をメソッド抽出した後に残る外側のブロック文 の機能の類似度 垂直結合度が閾値以上 内側のブロック文だけでなく外側のブロック文ごとメソッド抽出すべき SIGSS
20
ブロック文の垂直結合例 void METHOD() { …………………………… BLOCK1 { VAR v1,v2,v3,v4;
} void METHOD() { …………………………… BLOCK1 { VAR v1,v2,v3,v4; newMETHOD(v1,v2); } void newMethod(VAR v1, VAR v2) { BLOCK2 { VAR v5,v6 v5 = v1 + v2; v6 = v1 + v5; SIGSS
21
同一機能に属するブロック文群識別アルゴリズム
RESULT = NULL B = 特定されたブロック文 HCB = B と結合しているブロック文群(Bを含む) NHCB = B と水平結合していないブロック文群 OB = Bの外側のブロック文 if ( NHCB が空でない) if ( VC( OB, HCB ) > VC( OB, NHCB ) ) NHCBを新規メソッドとして抽出 else HCBを新規メソッドとして抽出 EXIT end if if ( OBとHCBが垂直結合している ) if ( OBがメソッド全体でない ) B = OB GOTO 行3 SIGSS
22
同一機能に属するブロック文群識別の例 void METHOD() { VAR v1, v2, v3, v4, v5; ……………………………
BLOCK1 { BLOCK2 { VAR v8 = v1 + v2; v6 = v3 + v8; v7 = v4 + v8; } VAR v9 = 0; BLOCK3 { v9 = v1 + v2 + v6; v5 = v7 + v9 BLOCK4 { BLOCK5 { VAR v12, v13, v14; v10 = v12 + v13 + v14; SIGSS
23
評価実験 対象言語: Java 対象ソフトウェア 評価基準 高品質なソフトウェア 低品質なソフトウェア バージョンの異なるソフトウェア
JHotDraw 低品質なソフトウェア 学生の書いたプログラムなど バージョンの異なるソフトウェア 評価基準 Bad smellの自動特定の妥当性 同一の機能に含まれる範囲識別の妥当性 適用すべきリファクタリングパターンの自動決定の妥当性 Next, I talk about our experiment. Target language is java. Target software is high-quality software such as JHotDraw and low quality software such as programs written by undergraduate students. If quality of target software is good, it is highly possible that there are few candidates of refactoring that are identified by our method. On the contrary, if quality of the target software is low, our method will identify many candidates of refactoring. Evaluation standards are adequacy of automatic identification of the spot should be refactored, adequacy of automatic determination of the applied refactoring and change of complexity metrics value. These experiments are under way SIGSS
24
適用例 抽出元メソッド 不吉な匂い(if1) If1,for3,for4が同一の機能 サイクロマチック数 12 行数 LVA 0.233
主観的判断 コードコメント 再利用可能な機能的単位 for3 for4 As a preliminary case study, we applied our method to a program written by a undergraduate student. In the interest of saving time, I show only one code fragments indentified by our method. This figure represent the code fragment, in this code fragment our method identified this “for-statement” and the surrounding code that are highlighted in gray as the target of “extract method”. In this “for-statement”, the number of available outer variables is 13, however, the number of really used outer variables is only 3. That means the vertical coupling between this “for-statement” and the outer block statement is low. So, it is easy to extract this “for-statement” from the outer block statement. In addition, there is no outer variable that is referenced in both this “for-statement” and the upper “for-statement”. That means the horizontal coupling between this “for-statement” and the upper “for-statement” is low. So, the upper “for-statement” is also not included in the extracted part. We think this identification is adequate also from a functional standpoint because of the code comments in the place. if1 SIGSS
25
関連研究 Eclipseのリファクタリング機能 基本ブロックスライシングによるメソッド抽出 Murphy-Hillらの研究
コード修正(リファクタリングプロセス4)の自動化 本手法と組み合わせることが可能 基本ブロックスライシングによるメソッド抽出 変数を1つ指定し,影響範囲をメソッドとして抽出 メソッドの機能は複数の変数を用いた計算により成立 絡み合ったコードを分割することができる Murphy-Hillらの研究 リファクタリングツール作成のガイドライン 軽快なツール 例外的なフォーマットへの対応 特定のタスクに特化した機能 SIGSS
26
まとめと今後の課題 まとめ 今後の課題 リファクタリングプロセスの一部を自動化するリファクタリング支援手法を提案した
ソフトウェアメトリクス ローカル変数のカプセル化 LVA 機能の抽象化 今後の課題 適用実験による定量的な評価 LVAとバグの相関調査 SIGSS
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.