Presentation is loading. Please wait.

Presentation is loading. Please wait.

コードクローンの分類に基づいた メソッド引き上げ手順の提案とその有効性評価

Similar presentations


Presentation on theme: "コードクローンの分類に基づいた メソッド引き上げ手順の提案とその有効性評価"— Presentation transcript:

1 コードクローンの分類に基づいた メソッド引き上げ手順の提案とその有効性評価
それでは、コードクローンの分類に基づいたメソッド引き上げ手順の提案とその有効性評価というタイトルで 井上研の吉岡が発表します 井上研究室  吉岡一樹

2 コードクローン ソースコード中のコード片で,同一または類似した コード片を持つもの コード片の修正 → コードクローンすべてに検討を 修正
コード片の修正 → コードクローンすべてに検討を 修正 修正を検討 ソースファイルF1 ソースファイルF2 クロ―ンペア クローンペア まず、研究の背景としてコードクローンについて説明します。 コードクローンとはソースコード中のコード片で,同一または類似したコード片を持つものです。 ここで表示されている例だとF1に二つの同一のコード片が、F2ににも同一のコード片があります。 これらをコードクローンと呼び,コードクローンの対のことをクローンペアと呼びます もしもコード片に 修正 クローンペア

3 リファクタリングパターンの開発は未熟な開発者の手助けに
外部的振る舞いに変更を加えずに内部的振る舞いを修 正することをリファクタリングという[1] 特に繰り返し行われる修正を,修正をする状況と手順をまと めてリファクタリングパターンという Fowlerはコードクローンに対する代表的なリファクタリン グパターンを提案している[1] 同一クラスのコードクローン → メソッドの抽出 兄弟クラスのコードクローン → メソッドの引き上げ リファクタリングパターンの開発は未熟な開発者の手助けに [1] Fowler.:Refactoring:”Improving The Design Existing Code”,Addison Wesley (1999)

4 より詳細なリファクタリングパターンを作成することで
既存のパターンの問題点 Fowlerのパターンでは,あいまいさを残すことで修正に 柔軟に対応するようにしている 対応できるだけの開発者の技術が必要になる 未熟な開発者が利用するには手順の詳細化が必要 数が少ないことの問題点 あいまいなことの問題点 ジョシュアも引用してみる? ×開発者の能力によらない より詳細なリファクタリングパターンを作成することで 未熟な開発者の手助けになる

5 コードクローンの分類 徳永らが提案したもの[2]でコードクローンの特徴ごとに分類 し,分類ごとにリファクタリングパターンを提案していく
分類項目は以下の7つ クローンペアの差異 クローンペアの位置 クローン部の長さ メソッド抽出の際に引数となるオブジェクト メソッド抽出の際に戻り値となるオブジェクトの数 制御構造要素の有無 Instanceof演算子の有無 上記の分類によってコードクローンを分類し,手順を詳細化 できるようにする 言わなくていい 後に必要になる奴だけいう [2]徳永将之ら,“コードクローンの分類に基づくリファクタリングパターンの提案に向けて”,ウインターワークショップ2011

6 本研究の提案内容 分類の一つを用いてリファクタリングパターンを提案 提案したパターンを用いて実験として被験者がリファクタ リング
Fowlerが提唱している既存パターンとの比較実験 提案したパターンの既存パターンの比較評価をアンケー ト アンケートでってはっきり言う 提案したパターンを既存パターンとの比較評価を行ってもらう

7 提案したパターン 要約 状況 ユーザ記述データ,定数を差異に持つ 兄弟クラス間クローンを親クラスに引き上げ 差異:上記の差異
ブロック単位 引数の権限:private 戻り値となるオブジェクトの数:0,もしくは1 制御構造要素なし Instanceof演算子なし リファクタリングパターンは, 状況 手順 実例 からなる文章で記述される 必要なとこだけ読む 本パターンは文章であらわした。 アイテマイズ //clear

8 以下の2つのコードは兄弟クラス間のクローンである
銀行口座のオブジェクト生成 顧客名のセット : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (ORDINARY_RATE); : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate ( FIXED_RATE); 顧客名のセット 顧客番号のセット 顧客番号のセット  !!アニメーション使う!! 差異

9 手順1:親クラスのメソッド宣言 手順1-1: メソッドの宣言,コンパイル 手順1-2: クローン部の引き上げ 手順1-3: 変数,オブジェクトの処理 手順1-4: 戻り値の処理 手順1-5: 差異の処理 手順1-6: 親クラスのコンパイル,テスト 手順2:子クラスのメソッド宣言

10 手順1-1: メソッドの宣言,コンパイル : : Account customer = Account customer =
手順1-1: メソッドの宣言,コンパイル : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); 親クラスに処理を記述する

11 メソッドの名前はメソッドの役割,処理の内容から決める
手順1-1: メソッドの宣言,コンパイル メソッドの名前はメソッドの役割,処理の内容から決める : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); void  initialAccount(){ }

12 手順1:親クラスのメソッド宣言 手順1-1: メソッドの宣言,コンパイル 手順1-2: クローン部の引き上げ 手順1-3: 変数,オブジェクトの処理 手順1-4: 戻り値の処理 手順1-5: 差異の処理 手順1-6: 親クラスのコンパイル,テスト 手順2:子クラスのメソッド宣言

13 手順1-2:クローン部の引き上げ : : Account customer = Account customer =
new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); void  initialAccount(){ }

14 手順1-2:クローン部の引き上げ : : void initialAccount(){ Account customer =
new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); void  initialAccount(){ Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (ORDINARY_RATE); } コピー&ペースト

15 手順1:親クラスのメソッド宣言 手順1-1: メソッドの宣言,コンパイル 手順1-2: クローン部の引き上げ 手順1-3: 変数,オブジェクトの処理 手順1-4: 戻り値の処理 手順1-5: 差異の処理 手順1-6: 親クラスのコンパイル,テスト 手順2:子クラスのメソッド宣言

16 手順1-3:クローン部の差異以外の変数,オブジェクトの引数を用意する
Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); void  initialAccount(){ Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (ORDINARY_RATE); }

17 手順1-3:クローン部の差異以外の変数,オブジェクトの引数を用意する
Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); void  initialAccount( String name,int number){ Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (ORDINARY_RATE); } 変数の名前をそのまま,引数に宣言する 右下簡潔に

18 手順1:親クラスのメソッド宣言 手順1-1: メソッドの宣言,コンパイル 手順1-2: クローン部の引き上げ 手順1-3: 変数,オブジェクトの処理 手順1-4: 戻り値の処理 手順1-5: 差異の処理 手順1-6: 親クラスのコンパイル,テスト 手順2:子クラスのメソッド宣言

19 手順1-4:戻り値があるならオブジェクトのreturnを追加し,メソッドの型を戻り値の型にする
Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); void  initialAccount( String name,int number){ Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (ORDINARY_RATE); } 右下簡潔に

20 手順1-4:戻り値があるならオブジェクトのreturnを追加し,メソッドの型を戻り値の型にする
Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); Account  initialAccount( String name,int number){ Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (ORDINARY_RATE); return customer; } 戻り値がないときにはこの手順での操作はない

21 手順1:親クラスのメソッド宣言 手順1-1: メソッドの宣言,コンパイル 手順1-2: クローン部の引き上げ 手順1-3: 変数,オブジェクトの処理 手順1-4: 戻り値の処理 手順1-5: 差異の処理 手順1-6: 親クラスのコンパイル,テスト 手順2:子クラスのメソッド宣言

22 手順1-5:差異のための引数を作成し,差異を引数で置き換える
Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); Account  initialAccount( String name,int number){ Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (ORDINARY_RATE); return customer; }

23 手順1-5:差異のための引数を作成し,差異を引数で置き換える
Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = (ORDINARY_RATE; : Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate () = FIXED_RATE); Account  initialAccount( String name,int number ,int rate){ Account customer = new Account(); customer.setName(name); customer.setNumber( number); customer.setRate (rate); return customer; } 共通部分を名前にしている ソースコード的にする 手順1-6:親クラスをコンパイルして,テストする

24 手順1:親クラスのメソッド宣言 手順1-1: メソッドの宣言,コンパイル 手順1-2: クローン部の引き上げ 手順1-3: 変数,オブジェクトの処理 手順1-4: 戻り値の処理 手順1-5: 差異の処理 手順1-6: 親クラスのコンパイル,テスト 手順2:子クラスのメソッド宣言

25 手順2:元の子クラスのクローン部を取り除き,メソッド呼び出しを追加する
Account customer = initialAccount(name, number, ORDINARY_RATE ); : Account customer= initialAccount(name, number, FIXED_RATE ); 何が変わったかわからない 各クラスをコンパイルして,テストする

26 適用実験の準備 提案したパターンを用いて、オープンソースソフトウェア Sootを用いて実際のコードでリファクタリングを行った
コードクローン検出ツールを用いてコードクローンを見つけた のち,手作業で分類にかけたもの 被験者三名に、3つのクローンペアに対し、提案したパ ターンとファウラーのパターンを比較してリファクタリング を行ってもらった 被験者はコンピュータサイエンス専攻のM1,M2,研究生の 三名 66個のJUnitテストを用いてリファクタリングが正常に行われた ことを確認する 口頭では口語

27 適用実験の結果(1/2) 提案手法が優れていると評価された点 提案手法が劣っていると評価された点 引数に対する扱い 戻り値があるときの扱い
手順1-3:変数,オブジェクトの処理を評価 戻り値があるときの扱い 手順1-4:戻り値の処理を評価 差異に対する扱い 手順1-5:差異の処理を評価 提案手法が劣っていると評価された点 手順全体の柔軟さ 詳細化を進めたために好みの手順でプログラミング出来ない

28 提案したパターンの手順の優位性を示している
適用実験の結果(2/2) 66個のJUnitテストケースを用いてリファクタリングパターンの妥当性を確認 被験者A 被験者B 被験者C 引数に対する扱い 戻り値があるときの扱い 差異に対する扱い 手順全体の柔軟さ スライド増やす 良かった点悪かった点を次のスライドで詳しく文章で 評価実験でいいところを手順で強調する ヴぉいdの話出す 開発者の要求に応じて手順変えれるようにする 時間は同じ 今のスライド 三名の評価で提案パターンが既存のパターンよりも優れていると 評価している箱の三点 ×禁止 悪い点も良い点と同様に表す 提案したパターンの手順の優位性を示している

29 まとめと今後の課題 まとめ 今後の課題 コードクローンの分類に基づいたメソッド引き上げ手順を提案 した
コードクローンの特徴ごとの分類の自動化 他の分類に対してのリファクタリングパターンの提案 ×Ccファインダー使うこと最初に言う

30 終わり


Download ppt "コードクローンの分類に基づいた メソッド引き上げ手順の提案とその有効性評価"

Similar presentations


Ads by Google