コードクローンを対象とした リファクタリングの有効性に関する調査

33
1 Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University コココココココココココココ ココココココココココココココココココ ココ ココ ココ ココ ココ ココ ココココ ココココココココココ {y-higo, kusumoto , inoue}@ist.osaka-u.ac.jp

Upload: lorand

Post on 23-Jan-2016

50 views

Category:

Documents


0 download

DESCRIPTION

コードクローンを対象とした リファクタリングの有効性に関する調査. 肥後 芳樹,楠本 真二,井上 克郎 大阪大学 大学院情報科学研究科 {y-higo, kusumoto, inoue}@ist.osaka-u.ac.jp. コードクローン. コードクローンとは ソースコード中に存在する一致または類似したコード片 コピーアンドペーストなどのさまざまな理由により生成される ソフトウェアの保守を困難にする あるコード片にバグがあると,そのコードクローン全てについて修正の検討を行う必要がある 機能を追加する場合も同様のことがいえる. コピーアンドペースト. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: コードクローンを対象とした リファクタリングの有効性に関する調査

1Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローンを対象としたリファクタリングの有効性に関する

調査肥後 芳樹,楠本 真二,井上 克郎

大阪大学 大学院情報科学研究科{y-higo, kusumoto, inoue}@ist.osaka-u.ac.jp

Page 2: コードクローンを対象とした リファクタリングの有効性に関する調査

2Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローン コードクローンとは

ソースコード中に存在する一致または類似したコード片コピーアンドペーストなどのさまざまな理由により生成

される

ソフトウェアの保守を困難にするあるコード片にバグがあると,そのコードクローン全て

について修正の検討を行う必要がある機能を追加する場合も同様のことがいえる

コピーアンドペーストコピーアンドペー

スト

Page 3: コードクローンを対象とした リファクタリングの有効性に関する調査

3Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

リファクタリング ソフトウェアの外部的な振る舞いを保ったままで,

内部構造を改善していくこと リファクタリングを行うことでソフトウェアの保守

性が増し,後の保守作業効率が向上する

これまでに多くのリファクタリングすべきコードのパターン( Bad Smell )とその対処法( Refactoring Pattern )が提案されている [1][2]

コードクローンは最も優先してリファクタリングを行うべきものの1つとされているしかし,具体的な評価事例はほとんど報告されていな

い[1] M. Fowler: Refactoring: Improving the Design of Existing Code, Addison-Wesley, 1999.

[2] Refactoring Home Page: http://www.refactoring.com/

Page 4: コードクローンを対象とした リファクタリングの有効性に関する調査

4Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

研究の目的と概要 コードクローンに対するリファクタリングのコスト

と効果を調査し,その有効性を評価する 実験対象は複数バージョンのソースコードが公開さ

れているオープンソースソフトウェア最初のバージョンに対してコードクローン検出 & リ

ファクタリングリファクタリングのコストとして以下のものを用い

たソースコード修正と回帰テストに要した時間

リファクタリングの効果として以下のものを用いたCK メトリクス値の変化総行数の増減集約箇所の後のバージョンでの修正回数

Page 5: コードクローンを対象とした リファクタリングの有効性に関する調査

5Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

CK メトリクス Chidamber と Kemerer が提案したオブジェクト指向ソフトウェ

アの複雑度を測定するメトリクス [3] であり,広く用いられている 各メトリクスは,クラス単位で計測される

WMC(Weighted Methods per Class): そのクラスに定義されているメソッドに重み付けをして足し合わせた値

DIT(Depth of Inheritance Tree): クラス階層における継承の深さ

NOC(Number of Children): サブクラスの数CBO(Coupling Between Objects): 関係しているクラスの数RFC(Response For a Class): そのクラスのオブジェクトに

メッセージが送られた結果,実行されうるすべてのメソッドの数を表す

LCOM(Lack of Cohesion Of Methods): そのクラスのメソッドがお互いに関連している程度を表す

[3] Chidamber S. R. and Kemerer C. F.: “A Metrics Suite for Object Oriented Design”, IEEE Transaction on Software Engineering, Vol. 20, No. 6, pp. 476-493 (1994).

Page 6: コードクローンを対象とした リファクタリングの有効性に関する調査

6Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローンに対するリファクタリング コードクローンは最も優先してリファクタリングを

行うべきコード(のパターン)の1つとされている

どのようにリファクタリングを行うかは,コードクローン間の関係によって異なる [1]

同一クラス内の複数個所が重複している場合兄弟クラス間で重複コードが見られる場合まったく関係のないクラス間で重複コードが見られる

場合

[1] M. Fowler: Refactoring: Improving the Design of Existing Code, Addison-Wesley, 1999.

Page 7: コードクローンを対象とした リファクタリングの有効性に関する調査

7Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローンに対するリファクタリング:同一クラス内の複数箇所が重複している場合 Extract Method を適用して,各メソッドの内部から

コードクローンを抽出し,新たなメソッドとして定義する.

抽出箇所は,そのメソッドの呼び出し文に変更する.void printTaxi(int amount){

String name = getTaxiName();

System.out.println(“ name:” + name);System.out.println(“ amount:” + amount);

}

void printBus(int amount){String name = getBusName();

System.out.println(“ name:” + name);System.out.println(“ amount:” + amount);

}

void printTaxi(int amount){String name = getTaxiName();print(name, amount);

}

void printBus(int amount){String name = getBusName();print(name, amount);

}

void print(String name, int amount){System.out.println(“ name:” + name);System.out.println(“ amount:” + amount);

}

void printTaxi(int amount){String name = getTaxiName();

System.out.println(“ name:” + name);System.out.println(“ amount:” + amount);

}

void printBus(int amount){String name = getBusName();

System.out.println(“ name:” + name);System.out.println(“ amount:” + amount);

}

void printTaxi(int amount){String name = getTaxiName();print(name, amount);

}

void printBus(int amount){String name = getBusName();print(name, amount);

}

void print(String name, int amount){System.out.println(“ name:” + name);System.out.println(“ amount:” + amount);

}

Page 8: コードクローンを対象とした リファクタリングの有効性に関する調査

8Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローンに対するリファクタリング兄弟クラス間で重複コードを共有している場合 各クラスに対して Extract Method を行い,次に Pull

Up Field や Pull Up Method を適用すれば解決する 場合によっては, Form Template Method などを適用

する場合もありうる

Employee

Salesman Engineer

getName() getName()

Employee

getName()

Salesman Engineer

Employee

Salesman Engineer

getName() getName()

Employee

getName()

Salesman Engineer

Page 9: コードクローンを対象とした リファクタリングの有効性に関する調査

9Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローンに対するリファクタリングまったく関係のないクラス間で重複コードが見られる場合 Extract Class を適用し,古いクラスから新しいク

ラスへと処理を委譲するように変更を行う

Person

nameofficeAreaCodeofficeNumber

Company

getTelephoneNumber()

addressofficeAreaCodeofficeNumber

getTelephoneNumber()

Person

name

getTelephoneNumber()

Company

address

getTelephoneNumber()

Telephon Number

areaCodenumber

getTelephoneNumber()

1

1 1

1

Person

nameofficeAreaCodeofficeNumber

Company

getTelephoneNumber()

addressofficeAreaCodeofficeNumber

getTelephoneNumber()

Person

name

getTelephoneNumber()

Company

address

getTelephoneNumber()

Telephon Number

areaCodenumber

getTelephoneNumber()

1

1 1

1

Person

nameofficeAreaCodeofficeNumber

Company

getTelephoneNumber()

addressofficeAreaCodeofficeNumber

getTelephoneNumber()

Person

name

getTelephoneNumber()

Company

address

getTelephoneNumber()

Telephon Number

areaCodenumber

getTelephoneNumber()

1

1 1

1

Page 10: コードクローンを対象とした リファクタリングの有効性に関する調査

10Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

本研究で扱うコードクローン コードクローンの一般的な定義はない

これまでにいくつかのコードクローン検出手法が提案されているが,それらはどれも異なった定義を持つ

リファクタリング可能なコードクローンを検出したいコードクローン検出に CCFinder[3] と CCShaper[4]

を用いる[3] T. Kamiya, S. Kusumoto, and K. Inoue, CCFinder: A multi-linguistic token-based code clone detec

tion system for large scale source code, IEEE Transactions on Software Engineering, vol. 28, no. 7, pp. 654-670, Jul. 2002.

[4] 肥後 芳樹,植田 泰士,神谷 年洋,楠本 真二,井上 克郎:コードクローン解析に基づくリファクタリングの試み,情報処理学会論文誌 , Vol.45, No.5, pp1357-1366, 2004-5

Page 11: コードクローンを対象とした リファクタリングの有効性に関する調査

11Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

クローンペアとクローンセット クローンペア

互いに一致または類似しているコード片の対(ペア)

クローンセット互いに一致または類似しているコード片の集合(セ

ット)C1

C2

C3

C4

C5

クローンペア

クローンセット

(C1, C2) {C1, C2, C4}

(C1, C4) {C3, C5}

(C2, C4)

(C3, C5)

Page 12: コードクローンを対象とした リファクタリングの有効性に関する調査

12Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローン検出ツール: CCFinder概要 ソースコードをトークン単位で直接比較することによ

り,コードクローンを検出する

より実用的なコードクローンを見つけることができるように設計されているユーザ定義名の置き換えテーブル初期化部分の取り除きモジュールの区切りの認識

検出結果はテキスト形式で出力

数百万行単位のソフトウェアからでも数十分で検出可能

Page 13: コードクローンを対象とした リファクタリングの有効性に関する調査

13Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

コードクローン抽出ツール:CCShaper概要 CCFinder が検出したコードクローンに含まれるプログラ

ミング言語の構造的なまとまりの部分を抽出コードクローン情報をリファクタリングに用いる場合に便

利CCFinder が検出するコードクローンはトークンの並びであ

り , 必ずしもリファクタリングの適用が容易なまとまりにはなっていない

現在は Java 言語のみに対応抽出するコードクローンの単位は以下の 12 個

宣言:クラス,インターフェース関数:メソッド,コンストラクタ,スタティックイニシャラ

イザ文: do, for, if, switch, synchronized, try, while,

Page 14: コードクローンを対象とした リファクタリングの有効性に関する調査

14Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

609: reset();610: grammar = g;611: // Lookup make-switch threshold in the grammar generic options612: if (grammar.hasOption("codeGenMakeSwitchThreshold")) {613: try {614: makeSwitchThreshold = grammar.getIntegerOption("codeGenMakeSwitchThreshold");615: //System.out.println("setting codeGenMakeSwitchThreshold to " + makeSwitchThreshold);616: } catch (NumberFormatException e) {617: tool.error(618: "option 'codeGenMakeSwitchThreshold' must be an integer",619: grammar.getClassName(),620: grammar.getOption("codeGenMakeSwitchThreshold").getLine()621: );622: }623: }624:625: // Lookup bitset-test threshold in the grammar generic options626: if (grammar.hasOption("codeGenBitsetTestThreshold")) {627: try {628: bitsetTestThreshold = grammar.getIntegerOption("codeGenBitsetTestThreshold");

623: }624:625: // Lookup bitset-test threshold in the grammar generic options626: if (grammar.hasOption("codeGenBitsetTestThreshold")) {627: try {628: bitsetTestThreshold = grammar.getIntegerOption("codeGenBitsetTestThreshold");629: //System.out.println("setting codeGenBitsetTestThreshold to " + bitsetTestThreshold);630: } catch (NumberFormatException e) {631: tool.error(632: "option 'codeGenBitsetTestThreshold' must be an integer",633: grammar.getClassName(),634: grammar.getOption("codeGenBitsetTestThreshold").getLine()635: );636: }637: }638:639: // Lookup debug code-gen in the grammar generic options640: if (grammar.hasOption("codeGenDebug")) {641: Token t = grammar.getOption("codeGenDebug");642: if (t.getText().equals("true")) {

コード片1

コード片2

CCFinder が検出するクローン

CCShaper が抽出するクローン

Page 15: コードクローンを対象とした リファクタリングの有効性に関する調査

15Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

1527: if ( inputState.guessing==0 ) {1528: t=a.getText();1529: }1530: {1531: _loop84:1532: do {1533: if ((LA(1)==COMMA)) {1534: match(COMMA);1535: id();1536: if ( inputState.guessing==0 ) {1537: t+=","+b.getText();1538: }1539: }

1007: if ( inputState.guessing==0 ) {1008: buf.append(a.getText());1009: } 1010: {1011: _loop144:1012: do {1013: if ((LA(1)==WILDCARD)) {1014: match(WILDCARD);1015: a=id();1016: if ( inputState.guessing==0 ) {1017: buf.append('.'); buf.append(a.getText());1018: }1019: }

コード片3 コード片4

CCFinder が検出するクローンペア

Page 16: コードクローンを対象とした リファクタリングの有効性に関する調査

16Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:概要 実験対象はオープンソースソフトウェア Ant

記述言語 : Java 15 バージョンのソースコードを用いた

バージョン番号: 1.1, 1.2, 1.3, 1.4, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.6.0, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5

最も古いバージョン (1.1) からコードクローン検出を行い,検出された全てのコードクローンに対してリファクタリングを試みた

リファクタリングのコストとして以下のものを用いた ソースコード修正と回帰テストに要した時間

リファクタリングの効果として以下のものを用いた CK メトリクス値の変化 総行数の増減 集約箇所の後のバージョンでの修正回数

Page 17: コードクローンを対象とした リファクタリングの有効性に関する調査

17Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:バージョン 1.1 に対するリファクタリング コードクローンのリファクタリングを行うために

CCFinder と CCShaper を用いて 50 トークン以上のコードクローンを検出

バージョン 1.1 の規模ソースファイル数: 83総行数: 19,986検出時間は約1分

7 個のクローンセットを検出そのうちの6つが実際にリファクタリングすることができたソースコード修正後,付属のテストケースを用いて回帰テストを行っ

その後の修正回数を調査するために バージョン 1.2 ~ 1.6.5 の該当箇所を調査

前のバージョンから修正を加わっているかどうかを diff で調査クローンセットになっているかを CCFinder と CCShaper を用いて

調査

Page 18: コードクローンを対象とした リファクタリングの有効性に関する調査

18Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:検出されたコードクローン 以下は検出されたコードクローンの概要である

実際はもっと回帰テストに時間がかかる付属のユニットテストしか行っていない,結合テストなども行

うべき

ID コード片数

単位 分類 時間

S0 2 メソッド 単一クラス内 7 分S1 6 メソッド 単一クラス内 19 分S2 2 メソッド 単一クラス内 -

S3 2 メソッド 単一クラス内 15 分S4 2 If 文 兄弟クラス間 14 分S5 2 メソッド 兄弟クラス間 5 分S6 2 メソッド 関係のないクラ

ス間17 分

Page 19: コードクローンを対象とした リファクタリングの有効性に関する調査

19Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:CK メトリクス値の変化 (1/3) S0 の CK メトリクス値の変化

S1 の CK メトリクス値の変化

S3 の CK メトリクス値の変化

クラス名 WMC DIT NOC CBO RFC LCOM

DirectoryScanner 21(+1) 1 0 0 47(+1) 158(+20)

クラス名 WMC DIT NOC CBO RFC LCOM

DirectoryScanner 21(+1) 1 0 0 47(+1) 158(+20)

クラス名 WMC DIT NOC CBO RFC LCOM

Task 17(+1) 1 23 4 24(+6) 98(+16)

$NestedElementHandler 4 2 0 4 14(-3) 0

$TaskHandler 4 2 0 7(-2) 21(-7) 0

リファクタリング前に比べてメトリクス値が悪化

リファクタリング前に比べてメトリクス値が改善

Page 20: コードクローンを対象とした リファクタリングの有効性に関する調査

20Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:CK メトリクス値の変化 (2/3) S4 の CK メトリクス値の変化

S5 の CK メトリクス値の変化

S6 の CK メトリクス値の変化クラス名 WMC DIT NOC CBO RFC LCOM

NewClass 2 1 0 2 7 1

JavacOutputStream 4 1 0 2(+1) 10(-1) 0

TaskOutputStream 3 1 0 2(+1) 8(-1) 0

クラス名 WMC DIT NOC CBO RFC LCOM

Javac 23(-1) 3 1 11 93 128(-105)

MatchingTask 16(+1) 2 11 5(+1) 56(+4) 94(+79)

Rmic 17(-1) 3 0 8 66(-2) 98(-17)

クラス名 WMC DIT NOC CBO RFC LCOM

ProjectHelper 15(+2) 1 0 7(+1) 66(+7) 79(+27)

Expand 4 2 0 5 35(-3) 2

Untar 4 2 0 8 36(-3) 2

Page 21: コードクローンを対象とした リファクタリングの有効性に関する調査

21Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:CK メトリクス値の変化 (3/3) コードクローンのリファクタリングは,必ずしも CK メトリク

ス値を改善するとは限らない 中には,クローンセット S0 や S1 のようにメトリクス値を悪化

させているだけのリファクタリングも存在した

CK メトリクスを測定するために ckjm を用いた このツールはメトリクス WMC として,単純にそのクラスで定

義されたメソッドの数を用いているWMC は Weigthed Method per Class の略本来は,各メソッドに対して重み付けを行った後,値を足し合わせ

る Extract Method のようにメソッド数が増えるリファクタリングの

場合は,必ず値が悪化してしまう サイクロマチック数などを用いて適切に重み付けをすれば,メ

ソッド数を増やすリファクタリングであっても WMC の改善があるかもしれない

Page 22: コードクローンを対象とした リファクタリングの有効性に関する調査

22Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:総行数の変化 下図は各クローンセットのリファクタリング後の総行数の変

化を表す

5 つのリファクタリングで総行数が減っている 多くても 20 行程度しか減っておらず,サイズ面で効果がある

とはいい難い “Extract Class” パターンを適用したリファクタリングは,新し

いクラスを作成したために,リファクタリング前に比べて行数が増えてしまっている

リファクタリング

S0 後 S1 後 S3 後 S4 後 S5 後 S6 後

行数 19,982

(-4)

19,964

(-22)

19,981

(-5)

19981

(-5)

19,962

(-24)

19,990

(+4)

Page 23: コードクローンを対象とした リファクタリングの有効性に関する調査

23Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:修正の流れ( 1/5 )(クローンセット S0 , S2 ) クローンセット S0

クローンセット S2

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0’ C0’’C0

C1 C1’’C1’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0’C0’ C0’’C0’’C0C0

C1C1 C1’’C1’’C1’C1’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0

C1

C0’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0C0

C1C1

C0’C0’

コード片は Cn で表され,修正が加わるたびに Cn’, Cn’’ と変化していく

同一クローンセットに含まれるコード片は長方形で囲まれる

Page 24: コードクローンを対象とした リファクタリングの有効性に関する調査

24Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:修正の流れ( 2/5 )(クローンセット S1 )1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0

C1 C1’’’

C2

C3

C4

C5

C2’

C3’

C4’

C5’

C6

C7

C8

C0’

C1’

C2’’

C3’’

C4’’

C5’’

C9

C8’

C9’

C0’’

C1’’

C0’’’

C2’’’

C3’’’

C4’’’

C5’’’

C8’’

C9’’

C7’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0C0

C1C1 C1’’’C1’’’

C2C2

C3C3

C4C4

C5C5

C2’C2’

C3’C3’

C4’C4’

C5’C5’

C6C6

C7C7

C8C8

C0’C0’

C1’C1’

C2’’C2’’

C3’’C3’’

C4’’C4’’

C5’’C5’’

C9C9

C8’C8’

C9’C9’

C0’’C0’’

C1’’C1’’

C0’’’C0’’’

C2’’’C2’’’

C3’’’C3’’’

C4’’’C4’’’

C5’’’C5’’’

C8’’C8’’

C9’’C9’’

C7’C7’

Page 25: コードクローンを対象とした リファクタリングの有効性に関する調査

25Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:修正の流れ( 3/5 )(クローンセット S3 , S4 ) クローンセット S3

クローンセット S4

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0

C1

C0’

C1’

C0’’

C1’’ C1’’’

C0’’’ C0’’’’

C1’’’’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0C0

C1C1

C0’C0’

C1’C1’

C0’’C0’’

C1’’C1’’ C1’’’C1’’’

C0’’’C0’’’ C0’’’’C0’’’’

C1’’’’C1’’’’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0

C1

C0’ C0’’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0C0

C1C1

C0’C0’ C0’’C0’’

Page 26: コードクローンを対象とした リファクタリングの有効性に関する調査

26Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:修正の流れ( 4/5 )(クローンセット S5 , S6 ) クローンセット S5

クローンセット S6

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0

C1

C0’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0C0

C1C1

C0’C0’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0

C1

C0’

1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5

C0C0

C1C1

C0’C0’

Page 27: コードクローンを対象とした リファクタリングの有効性に関する調査

27Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

実験:修正の流れ( 5/5 ) リファクタリング箇所の後のバージョンでの修正回数はクロ

ーンセットによってさまざまであった

全てのクローンセットがバージョンをまたいで存在しているわけではなく,各コード片に対して異なる修正が加わった結果,コードクローンでなくなる場合もあった.本実験では7つクローンセットのうちの4つこれらのクローンセットには一度も共通の修正がなかった

一度でも共通の修正が加わった場合は,その後も修正される傾向がある実際に全てのコード片に同様の修正が加わった場合にリファクタ

リングを行うことで,その後の修正回数を減らすことができるのでは?

Page 28: コードクローンを対象とした リファクタリングの有効性に関する調査

28Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

考察 リファクタリングが有効であるかどうかは,その効果がコス

トを上回っているかどうかで決まる 例:クローンセット S0

コスト:ソースコード修正と回帰テストに7分を要した効果( CK メトリクス): WMC , RFC , LCOM が悪化効果(修正回数):バージョン 1.5 と 1.6.3 での修正箇所が 2

つから1つに減った 効果とコストの大小関係は一意に決めることができない

本実験で行ったリファクタリングは,基本的かつ汎用的であり,ソースコード修正を行う者のスキルや対象ソフトウェアのドメインを限定するものではない

リミテーション リファクタリングの規模が小さい メトリクス値で調査したのは複雑度の変化のみ

他の面からの評価も必要である

Page 29: コードクローンを対象とした リファクタリングの有効性に関する調査

29Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

まとめ コードクローンに対するリファクタリングのコストと効果を調

査した 実験対象は 15 バージョンのソースコードが公開されているオー

プンソースソフトウェア その最初のバージョンに対してリファクタリングを行った

コストの尺度 ソースコード修正と回帰テストに要した時間

効果の尺度 CK メトリクス値の変化 総行数の増減 集約箇所の後のバージョンでの修正回数

こらからの予定 コスト・効果項目を増やす企業ソフトウェアでも実験を行う( + 開発者へのインタビュー)

Page 30: コードクローンを対象とした リファクタリングの有効性に関する調査

30Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

Page 31: コードクローンを対象とした リファクタリングの有効性に関する調査

31Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

Source files

字句解析

変換処理

トークン列

検出処理

変換後トークン列

クローン情報

出力整形処理

クローンペア位置情報

コードクローン検出ツール : CCFinder検出プロセス

1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. }10. static void goo(String [] a) throws RESyntaxException {11. RE exp = new RE("[0-9,]+");12. int sum = 0;13. for (int i = 0; i < a.length; ++i)14. if (exp.match(a[i]))15. sum += parseNumber(exp.getParen(0));16. System.out.println("sum = " + sum);17. }

static void foo ( ) { String a

[ ] = new String [ ] { "123,400" ,

"abc" , "orange 100" } ;

int sum = 0

; for ( int i = 0 ; i <

a . length ; ++ i )

sum

+= pat . getParen 0

; System . out . println ( "sum = "

+ sum ) ; }

throws RESyntaxException

Sample . parseNumber (

) )

if pat

. match a [ i ]( ) )

org . apache . regexp

. RE pat = new org . apache . regexp

. RE ( "[0-9,]+" ) ;

static void goo (

) {

String

a [ ]

int sum = 0

; for ( int i = 0 ; i <

a . length ; ++ i )

System . out . println ( "sum = " + sum

) ; }

throws RESyntaxException

if exp

. match a [ i ]( ) )

exp =

new RE ( "[0-9,]+" ) ;

(

RE

sum

+= exp . getParen 0

;

parseNumber ( ) )(

(

(

[ ] = new String [ ] {

} ;

int sum = 0

; for ( int i = 0 ; i <

a . length ; ++ i )

sum

+= pat . getParen 0

; System . out . println ( "sum = "

+ sum ) ; }

Sample . parseNumber (

) )

if pat

. match a [ i ]( ) )

pat = new

RE ( "[0-9,]+" ) ;

static void goo (

) {

String

a [ ]

int sum = 0

; for ( int i = 0 ; i <

a . length ; ++ i )

System . out . println ( "sum = " + sum

) ; }

throws RESyntaxException

if exp

. match a [ i ]( ) )

exp =

new RE ( "[0-9,]+" ) ;

(

RE

sum

+= exp . getParen 0

;

parseNumber ( (

(

(

static void foo ( ) { String athrows RESyntaxException

$

RE

$ . ) )

字句解析

変換処理

トークン列

検出処理

変換後トークン列

クローン情報

出力整形処理

[ ] = new String [ ] {

} ;

int sum = 0

; for ( int i = 0 ; i <

a . length ; ++ i )

sum

+= pat . getParen 0

; System . out . println ( "sum = "

+ sum ) ; }

Sample . parseNumber (

) )

if pat

. match a [ i ]( ) )

pat = new

RE ( "[0-9,]+" ) ;

static void goo (

) {

String

a [ ]

int sum = 0

; for ( int i = 0 ; i <

a . length ; ++ i )

System . out . println ( "sum = " + sum

) ; }

throws RESyntaxException

if exp

. match a [ i ]( ) )

exp =

new RE ( "[0-9,]+" ) ;

(

RE

sum

+= exp . getParen 0

;

parseNumber ( ) )(

(

(

static void foo ( ) { String athrows RESyntaxException

$

RE

$ .

[ ] = [ ] {

} ;

=

; for ( = ; <

. ; ++ )

+= .

; . . (

+ ) ; }

. (

) )

if

. [ ]( ) )

=

( ) ;

static (

) {[ ]

=

; ( = ; <

. ; ++ )

. . ( +

) ; }

throws

if

. [ ]( ) )

=

new ( ) ;

(

+= .

;

( ) )(

(

(

static $ ( ) {throws

$

$ .

$ $ $ $

$ $

$ $

$ $ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $ $

new

forfor

new

[ ] = [ ] {

} ;

=

; for ( = ; <

. ; ++ )

+= .

; . . (

+ ) ; }

. (

) )

if

. [ ]( ) )

=

( ) ;

static (

) {[ ]

=

; ( = ; <

. ; ++ )

. . ( +

) ; }

throws

if

. [ ]( ) )

=

new ( ) ;

(

+= .

;

( ) )(

(

(

static $ ( ) {throws

$

$ .

$ $ $ $

$ $

$ $

$ $ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $

$ $ $ $ $

字句解析

変換処理

トークン列

検出処理

変換後トークン列

クローン情報

出力整形処理

1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. }10. static void goo(String [] a) throws RESyntaxException {11. RE exp = new RE("[0-9,]+");12. int sum = 0;13. for (int i = 0; i < a.length; ++i)14. if (exp.match(a[i]))15. sum += parseNumber(exp.getParen(0));16. System.out.println("sum = " + sum);17. }

字句解析

変換処理

トークン列

検出処理

変換後トークン列

クローン情報

出力整形処理

Page 32: コードクローンを対象とした リファクタリングの有効性に関する調査

32Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University

リファクタリングできなかったクローンセット S2

コード片 C0

コード片 C1

protected void fireTargetStarted(Target target) { BuildEvent event = new BuildEvent(target); for (int i = 0; i < listeners.size(); i++) { BuildListener listener = (BuildListener) listeners.elementAt(i); listener.targetStarted(event); }}

protected void fireTaskStarted(Task task) { BuildEvent event = new BuildEvent(task); for (int i = 0; i < listeners.size(); i++) { BuildListener listener = (BuildListener) listeners.elementAt(i); listener.taskStarted(event); }}

Page 33: コードクローンを対象とした リファクタリングの有効性に関する調査

33Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University