210 likes | 330 Views
同一メソッド内に含まれる ブロック間の結合度を用いた メソッド分割手法の提案. 井上研究室 M 2 三宅達也. 研究概要. ソフトウェアの設計品質を高く保つことが重要 ⇒ソフトウェアの設計品質を向上させるための技術 メソッド抽出リファクタリングを支援する手法の提案. メソッド抽出リファクタリング. メソッド内のコードの一部を新規メソッドとして抽出 既存の1つのメソッドを2つの短いメソッドに分割 メソッド抽出リファクタリングの手順 メソッド抽出リファクタリングを必要とするメソッドを特定 新規メソッドとして抽出する範囲を識別 識別範囲をメソッドとして抽出
E N D
同一メソッド内に含まれるブロック間の結合度を用いたメソッド分割手法の提案同一メソッド内に含まれるブロック間の結合度を用いたメソッド分割手法の提案 井上研究室 M2三宅達也
研究概要 • ソフトウェアの設計品質を高く保つことが重要 ⇒ソフトウェアの設計品質を向上させるための技術 • メソッド抽出リファクタリングを支援する手法の提案
メソッド抽出リファクタリング • メソッド内のコードの一部を新規メソッドとして抽出 • 既存の1つのメソッドを2つの短いメソッドに分割 • メソッド抽出リファクタリングの手順 • メソッド抽出リファクタリングを必要とするメソッドを特定 • 新規メソッドとして抽出する範囲を識別 • 識別範囲をメソッドとして抽出 • プログラムの振る舞いが変わっていないか検証
メソッド抽出の例と特徴 public void sample ( ) { int i = 0; while( hoge() ) { String str = “string”; if( jar( i ) ) { make(str); } for( int j = 0; j < i ; j++) { sam( i ); if( log ) { System.out.println(str); } } } while( ) { bar(i); } } public void sample ( ) { int i = 0; while( hoge() ) { printStr(i); } while( ) { bar(i); } } public void printStr(int i) { String str = “string”; if( jar( i ) ) { make(str); } for( int j = 0; j < i ; j++) { sam( i ); if( log ) { System.out.println(str); } } } • 短いメソッドを形成する • 他のメソッドから利用しやすい • 再利用性の向上 • 重複コードの生成防止 • 適切な命名を行うことで、内部の処理の理解が容易になる • 可読性の向上 • オーバライドが行いやすい • 拡張性の向上 抽出
研究の動機と目的 • 研究動機 メソッド抽出リファクタリングは • さまざまな利点を持つ • 頻繁に行われる普遍的な作業 • 他の品質向上作業の前準備 ⇒自動化の効果が大きい • 研究目的 • メソッド抽出リファクタリングを支援する手法を提案 • 新規メソッドとして抽出すべき範囲を自動的に特定
適切なメソッド抽出 • 機能に基づいて分割されたメソッド • 機能:1つのメソッドが実現する特定の処理 • 引数の少ないメソッド • 呼び出し元のメソッドとの依存関係が小さい • 引数の役割が理解しやすい ⇒ 凝集度の高いメソッド • メソッドの構成要素が協調 • メソッドが適切に役割分担されている • メソッド内の構成要素が密結合 • メソッド内部と外部の要素は疎結合
提案手法の概要 • 新規メソッドとして抽出する範囲を自動的に識別 • メソッド内のコードが実現する機能を変数集合で表現 • コードブロック間の結合度を定義 • 互いに強く結合しているコードブロック群を識別 新規メソッドとして抽出するコードブロック群
変数を用いた機能の表現 • メソッドの機能:変数の値を決定するための計算[23] • 変数を指定することはメソッドの機能を指定することと同義 • 過去の研究では返り値のみに着目 • 提案手法ではメソッド内で使用されている全変数に着目 ⇒コード片B の機能を変数集合V(B)で表す [23]丸山.基本ブロックスライシングを用いたメソッド抽出リファクタリング. 情報処理学会論文誌43(6):1625-1637, Jun 2002.
コード片の協調度合 • 変数集合の共通要素が要素数の少ない変数集合を占める割合 • 協調度合が高いとき2つのコード片は同一の機能を実現するためのコード片である可能性が高い 共通要素の数 要素数の少ない変数集合の要素数
コードブロック間の関係 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); make(str); } } sample ( ) while while if for 親子関係 兄弟関係 if
兄弟ブロック結合 • 兄弟関係にあるコードブロック間の結合度 • 兄弟関係にあるコードブロックの機能の協調度合 • B1とB2が兄弟関係にある時 • 兄弟ブロック結合度が閾値以上 • 2つのコードブロックを1つのメソッドとして抽出
親子ブロック結合 • 親子関係にあるコードブロック間の結合度 • 子コードブロック の機能と をメソッド抽出した後に残る親コードブロック の機能の協調度合 • 親子ブロック結合度が閾値以上 • 子コードブロックだけでなく親コードブロックごとメソッド抽出
同一機能に属するコードブロック群識別アルゴリズム同一機能に属するコードブロック群識別アルゴリズム • RESULT = NULL • B = 特定されたコードブロック • SCB = B と結合しているコードブロック群(Bを含む) • NSCB = B と兄弟ブロック結合していないコードブロック群 • PB = Bの親コードブロック文 • if ( NSCB が空でない) • if ( PBC( PB, SCB ) > PBC( PB, NSCB ) ) • NSCBを新規メソッドとして抽出 • else • SCBを新規メソッドとして抽出 • EXIT • end if • end if • if ( PBとSCBが親子ブロック結合している ) • if ( PBがメソッド全体でない ) • B = PB • GOTO行3 • end if • else • SCBを新規メソッドとして抽出 • end if
同一機能に属するブロック文群識別の例(閾値: 0.5) 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; …………………………… v9 = v12 + v13 + v14; } } } SBC: 0.75 PBC: 0.66 SBC: 0.25
適用事例 for1 for2 • 対象 • 学生の書いたプログラム • If1,for3,for4が同一の機能を実現するためのコードブロック群 • 主観的判断 • コードコメント • 再利用可能な機能的単位 for3 for4 if1
考察 • 改善案 • 変数ごとに重要度を定義 • 重要度の高い変数が協調しているほど高結合 • 適用範囲 • 1つのコードブロックは1つの機能に対応 • ブロックの構造を壊すようなメソッド抽出には未対応 • ある程度規模の大きなメソッドが対象 • 複数のコードブロック • 複数の使用変数
まとめと今後の課題 • まとめ • メソッド抽出リファクタリングを支援する手法を提案 • 新規メソッドとして抽出する範囲を自動特定 • 今後の予定 • 実験の拡大 • 実験対象の追加による汎用性の検証 • リファクタリングの問題点の解決に関する定量的な評価
変数を用いた機能の抽象化例 void METHOD() { VAR v1, v2, v3; …………………………… BLOCK1 { VAR v4,v5; …………………………… BLOCK2 { v4 = v1 + v2; } …………………………… BLOCK3 { v5 = v1 + 4; } v5 = v1 + v2 } …………………………… }
親子ブロック結合度の算出例 void METHOD() { …………………………… BLOCK1 { VAR v1,v2,v3,v4; …………………………… BLOCK2 { VAR v5,v6 v5 = v1 + v2; v6 = v1 + v5; } …………………………… } …………………………… } 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; } }
関連研究 • Eclipseのリファクタリング機能 • コード修正(リファクタリングプロセス4)の自動化 • 本手法と組み合わせることが可能 • 基本ブロックスライシングによるメソッド抽出 • 変数を1つ指定し,影響範囲をメソッドとして抽出 • メソッドの機能は複数の変数を用いた計算により成立 • 絡み合ったコードを分割することができる • Murphy-Hillらの研究 • リファクタリングツール作成のガイドライン • 軽快なツール • 例外的なフォーマットへの対応 • 特定のタスクに特化した機能
メソッド抽出リファクタリング • メソッドの一部を新しいメソッドとして抽出 • 対象 • 長すぎるメソッド • 複雑な制御構造をもつメソッド • 効果 • 再利用性の向上 • 適切な命名を行うことで内部の処理の可読性が向上 • 拡張性の向上 • 普遍的で頻繁に行われるリファクタリングパターン ⇒自動化の効果が大きい