xabcabc* a* b* c* y - Software Engineering Laboratory

Download Report

Transcript xabcabc* a* b* c* y - Software Engineering Laboratory

コードクローン分析ツールGeminiを
用いたコードクローン分析手順
大阪大学 大学院情報科学研究科
肥後 芳樹([email protected])
楠本 真二([email protected])
井上 克郎([email protected])
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
背景

コードクローンとは
 ソースコード中に存在する一致または類似したコード片
 コピーアンドペーストなどのさまざまな理由により生成される
copy-and-paste

copy-andpaste
ソフトウェアの保守を困難にする
 あるコード片にバグがあると,そのコードクローン全てについて修
正の検討を行う必要がある
 機能を追加する場合も同様のことがいえる
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローンに対するこれまでの取り組み

コードクローンに対する支援ツールの開発
 検出ツール:
CCFinder[1]
 分析ツール: Gemini[2]

CCFinder/Geminiパッケージとして国内外の個人・組織に配布
 研究機関での利用
 企業での試用・商用ソフトウェアの開発プロセスへの導入

配布先からのフィードバック
 バグ報告,新機能の提案
 分析手順に関する問い合わせ
 Geminiを用いたコードクローン分析方法を提案する
[1] T. Kamiya, S. Kusumoto, and K. Inoue, “CCFinder: A multi-linguistic token-based code clone detection system for large scale source code”,
IEEE Transactions on Software Engineering, 28(7):654-670, 2002.
[2] Y. Ueda, T. Kamiya, S. Kusumoto and K. Inoue, “Gemini: Maintenance Support Environment Based on Code Clone Analysis”,
Proc. Of the 8th IEEE International Symposium on Software Metrics, 67-76, 2002.
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローンを用いた分析の目的

設計とコードの一貫性確認
 設計情報で重複している部分はソースコードでも重複しており,それ以
外の部分には重複をしている部分がないかを確認する

信頼性の改善
 長期間保守をされているシステムのソースコードには多くのコードクローン
が存在する可能性が高い
 新たな保守作業の際に,保守対象のコード片に対するコードクローンを
調査することで,変更漏れを防ぐことが可能となる

保守性の改善
 複数のバージョンのソースコードが与えられたときに,バージョン間でのコー
ドクローンの遷移を調査し,保守作業の効率化を計る
 繰り返し修正が加えられているコードクローンは集約する
 安定しているコードクローンにはリファクタリングは不要
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
クローンペアとクローンセット
クローンペア: 互いに一致・類似しているコード片の対
 クローンセット: 互いに一致・類似しているコード片の集合

C1
クローンペア
(C1, C4)
クローンセット
{C1, C4, C5}
C2
(C1, C5)
{C2, C3}
C3
(C2, C3)
C4
(C4, C5)
C5
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローン検出ツール CCFinder
概要:

ソースコードをトークン単位で直接比較することにより
コードクローンを検出
 名前空間の正規化
 ユーザ定義名の置き換え
 テーブル初期化部分の取り除き
 モジュールの区切りの認識
解析結果はテキスト形式で出力
 数百万行規模でも実用的な時間で解析可能

Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローン検出ツール CCFinder
検出プロセス:
Source files
static
throws
{{{ String
1. static
static
foo()
throws
RESyntaxException
{
{{ $$ $$
(( (( )) ))throws
$void
void
foofoo()
throws$$RESyntaxException
RESyntaxException
String aaa {
static
RESyntaxException
String
1.
void
throws
RESyntaxException
static void
$ $$foo
throws
]{{] {${$ "123,400"
,
[[ [][] String
$String
$$ =
new
$[] {
]]] === a[]
new
$[]
2. [[String
a[]
=
new
String
{ "123,400",
"123,400",
"abc", "orange
"orange 100"
100" };
};
2.
new
"abc",
[String
$String
"abc"
,
"orange
100"
}
;
org
.
apache
.
regexp
;
}
} ;
3. org.apache.regexp.RE
org.apache.regexp.RE
pat == new
new org.apache.regexp.RE("[0-9,]+");
org.apache.regexp.RE("[0-9,]+");
3.
pat
$$ === new
$$ pat
RE
pat
RE
new
4. .int
int
sum
0; org . apache . regexp
4.
sum
==new
0;
. RE
)) ;;; int
$$ ==== $0$00
$$ sum
$$
$$ ((( "[0-9,]+"
RE
int
sum
sum
5. for
for
(int"[0-9,]+"
i == 0;
0; ii) << a.length;
a.length;
++i)
5.
(int
i
++i)
;; for
$$ i$$i === 0$0$ ;;; i$$i <<<<
int
for (( int
6. a$ ifif. (pat.match(a[i]))
(pat.match(a[i]))
6.
;++
$$ ii)) ))if
$$ ;; ++
length
; ++
++
pat
pat
$ . length
if ifif(( ((($$ pat
7. .. match
sum
+=
Sample.parseNumber(pat.getParen(0));
7.
sum
+=
Sample.parseNumber(pat.getParen(0));
$$ (( (( $$ aa [[ [[ $$ ii ]] ]] )) )) )) ))) $$sum
sum
sum
. match
8.
System.out.println("sum
" ++ sum);
sum);
8. +=
System.out.println("sum
"getParen
+=
Sample
((( 000
(( $$ .. $$ (( ((pat
$$ .. $.$. parseNumber
parseNumber
pat$$ .=
. getParen
pat
.=
getParen
+=
9. }} )) )) ;; System
(( $$ ((( "sum
.. .$$. println
$$ .. .$$. out
System
out
println
"sum==="""
9.
println
"sum
static
String
$$ $$goo
}}} static
))) ;;; goo(String
$$ void
sum
static void
void
goo
String
10. static
static
void
goo(String
[]((a)
a)((( $$throws
throws
RESyntaxException {{
+++ sum
goo
String
10.
[]
RESyntaxException
static
{{ $$ $$ =
$$RE("[0-9,]+");
throws
RESyntaxException
RE exp
exp ===
[[[ exp
]]] )))=
RESyntaxException
RE
exp
11. a$a$RE
RE
exp
=throws
newRESyntaxException
throws
= {{{ RE
11.
new
RE("[0-9,]+");
new
RE
=
$$ )) ;;)) $$;; $$int
$$ (( "[0-9,]+"
int sum
sum
new
=sum$$=== 000
12. new
int
sum"[0-9,]+"
0;
12.
int
sum
== 0;
$$ i$$i === 0$0$ ;;; i$$i <<<<
for
int
for
((( int
for (int
13. ;;;for
for
0; ii << a.length;
a.length; ++i)
++i)
13.
(int
ii == 0;
$
(
$$ ii)) ))if
$$ ;; ++
if
(
exp
length
; ++
++
if
(
exp
a$a$ ... length
;++
(
exp
if ( $
14. . match
(exp.match(a[i]))
14.
ifif (exp.match(a[i]))
]
$
[
$
(
$
(
a
[
i
]
(
a
[
i
]
sum
sum
. $ ( $ [ $ ] )) )) )) ))) $$sum
15. +=
sum
+=
parseNumber(exp.getParen(0));
15.
sum
+=
parseNumber(exp.getParen(0));
(( .. $$ getParen
$$ (( ( $$exp.. ((. $$exp
+=
getParen
()) 0)) )(( )00 )) ))
parseNumber
exp
getParen
$$$ ... parseNumber
+= parseNumber
16. ;;;System.out.println("sum
System.out.println("sum
==="""""+++++sum
sum);
16.
sum);
$$ =
(( $$ ((++ "sum
.. .$$. println
$$ .. .$$. out
=
System
out
println
"sum
sum
System
"sum
sum
17. }}))) ;;; }}}
17.
字句解析
字句解析
トークン列
トークン列
変換処理
変換処理
変換後トークン列
変換後トークン列
検出処理
検出処理
クローン情報
クローン情報
出力整形処理
出力整形処理
クローンペア位置情報
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローン分析ツール Gemini
概要:

CCFinderの解析結果(テキストファイル)を読み込み,コード
クローン情報を視覚的に表示
 クローン散布図(スキャタープロット図)
 メトリクスグラフ

重要でないコードクローンのフィルタリング
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローン分析ツール Gemini
クローン散布図:

 原点は左上隅

はその水平方向のトークンと垂
直方向のトークンが等しいことを意
味する
 常に対角線が引かれる
 クローンペアは線分として出現する
 対角線に対して線対称となる
a b c a b c a d e c
a b c a b c a d e c
水平・垂直方向にソースコード中
のトークンを出現順に配置
a, b, c, ... : tokens
: matched position
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローン分析ツール Gemini
メトリクスグラフ(概要)


メトリクスを用いてクローンセットを定量的に特徴づける
多次元並行座標表現を用いている
 各メトリクスにつき1つの座標軸が存在する
 各クローンセットにつき1つの折れ線がメトリクス値に基づいて描画される
S1
S1
S2
S2
RAD

LEN
RNR
POP
NIF
RAD
LEN
RNR
POP
NIF
ユーザは各メトリクスの上限・下限を変更することでクローンセットの選
択・選択解除を行う
 全てのメトリクスが上限と下限の間にあるクローンセットが選択状態になる
 選択状態にあるクローンセットのソースコードは簡単に閲覧可能
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローン分析ツール Gemini
メトリクスグラフ(用いているメトリクス):





LEN(S): クローンセット S 内に含まれるコード片のトークン数の平均
値を表す
POP(S): S に含まれるコード片の数を表す
RAD(S): S 内のコード片がファイルシステム上でどの程度分散してい
るかを表す
NIF(S): S に含まれるコード片を所有しているファイルの数を表す
RNR(S): 次項で説明
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
コードクローン分析ツール Gemini
重要でないコードクローンのフィルタリング:

CCFinderの検出するコードクローンはトークンの列であり,重要でない
コードクローンを多数検出してしまう
 switch文の各caseエントリ
 連続したimport文,

フィルタリングメトリクス RNR(S)
 クローンセット

printf文, scanf文 など
S に含まれるコード片の非繰り返し度を表す
例 トークン列 <x a b c a b c* a* b* c* y>
 CCFinder
は以下の2つのコード片をコードクローンとして検出
 x a b c a b c*<F1> a* b* c* y
 x a b c a b c* a* b* c*<F2> y
 F1はコード片の長さが6トークン,そのうち5トークンが非繰り返し
 F2はコード片の長さが6トークン,そのうち2トークンが非繰り返し
 RNR(S1)
= (5 + 2)/(6 + 6) = 7/12 = 0.583
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
各ビューの特徴
クローン散布図:

コードクローンの分布状態を俯瞰的に知ることができる

以下の部分が目立ちやすい
 ある程度の領域内にコードクローンが密集している部分
 繰り返し同じパターンが出現している部分

ファイルよりも大きな単位での類似部分を知ることができる
 ディレクトリ・モジュール単位での類似部分など

クローン散布図において目立つ部分は,必ずしもその部分に存在するコードクローン
が特徴的であることを示しているわけではない
 目立つ部分に存在するコードクローンは一種類ではなく,複数の種類のコードク
ローンが混在している場合がある

目立ちやすさとコードクローンの位置が関係している
 要素数の多いクローンセットであっても,そのコード片が複数のファイル内に散在
している場合は,クローン散布図上ではそれらは離れた位置に描画される
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
各ビューの特徴
メトリクスグラフ:

定量的に特徴的なコードクローンを見つけることができる
 コードクローンの位置に影響されることはない

メトリクスRAD,NIFを用いて,クローンセットに含まれるコード片がファ
イルシステム上でどの程度散らばっているかを知ることができる
はクローンセット S の垂直方向への広がりの程度を表す
 NIF(S) は S の水平方向への広がりの程度を表す
 RAD(S)
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
提案する分析法
概要:

Gemini を用いた効果的と思われる分析法を提案する
大まかな把握
 STEP2A: 要素数の多いクローンセットの特定
 STEP2B: トークン数の多いクローンセットの特定
 STEP2C: 多くのファイルを巻き込んでいるクローンセットの特定
 STEP1:
 (STEP2A)~(STEP2C)は順序不同
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
効果的な分析法
STEP1(大まかな把握):

新規でコードクローン分析を行う場合は,まずクローン散布図を用いて
コードクローンの分布状態を大まかに把握するとよい

クローン散布図では,マウスカーソル位置の水平・垂直方向のファイル
のパスがリアルタイムで表示される
 目立つ部分にマウスカーソルを移動させるだけで,その部分がどのファイル
なのかを知ることができる

以下の2つの部分が目立ちやすい部分である
 一定の領域内にコードクローンが密集している部分
 同じようなパターンが繰り返し出現している部分

メトリクス RNR の値が閾値未満のコードクローンは青色,以上のコー
ドクローンは黒色で描画
 閾値はユーザが自由に設定可能
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
提案する分析法
STEP2A(要素数の多いクローンセット):

要素が多いということは,その機能がソフトウェアの多くの箇所で実装さ
れていることを表している
 ソフトウェアの象徴的な処理部分であるとも考えられる
 その部分にバグが検出された場合,多くの箇所に同様の修正を加えなけ
ればならない
 リファクタリングの対象とすべき?

要素数の多いクローンセットの特定にはメトリクスグラフを用いる
 要素数を表すメトリクスは
POP
 メトリクス RNR も同時に用いた方が望ましい
 繰り返し部分は要素数の多いクローンセットになりがち
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
提案する分析法
STEP2B(トークン数の多いクローンセット):

トークン数の多いコードクローンはコピーアンドペーストにより生成された
ものではないかと思われる
 ペースト後の変数名やメソッド名の修正漏れがバグに繋がる
 修正漏れのチェックを行うのは効果的な予防保守

トークン数の多いクローンセットの特定にはメトリクスグラフを用いる
 トークン数を表すメトリクスはLEN
 メトリクス
RNR も同時に用いた方が望ましい
 if文やcase文が数十回繰り返し存在する場合がある
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
提案する分析法
STEP2C(多くのファイルを巻き込んでいるクローンセット):

根本的な問題を表している可能性がある
 設計が悪いことを暗示
 プログラミング言語に適切な抽象化機構が存在しない(横断的関心事)

多くのファイルを巻き込んでいるクローンセットの特定にはメトリクスグラフ
を用いる
 巻き込んでいるファイル数を表すメトリクスは
NIF
 メトリクス RNR も同時に用いたほうが望ましい
 Switch文の連続したCaseエントリが繰り返しの多いクローンとなってしまう
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験

目的
 提案した分析手法によってどのようなコードクローンが見つかる
かを調査する

オープンソースソフトウェア Ant (version 1.6.0)
 ビルドツールの一種,Java言語で記述されている
 ソースファイル数:
627
 総行数: 約18万行

検出対象: 30トークン以上
 2,406個のクローンセット
 190,004個のクローンペア
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験
STEP1: 大まかな把握(全体)


右図は対象ソースコード全
体を表したクローン散布図
A
A, B, Cの部分がどのような
コードクローンであるかを調
査した
B
C
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験
STEP1:大まかな把握(Aの部分)

クローンの場所: ファイルを読み込
む機能を実装している部分
 先頭の数行のみを読み込み
 ユーザが指定した文字列を含む
行のみを読み込み
 各行にプレフィックスを付けて読み
込み

クローンが実装している機能:
 ストリームから1文字読み込む.終端まできたら,それに応じた処理をする
 新しく
java.io.Reader オブジェクトを生成し,それを返す
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験
STEP1:大まかな把握(Bの部分)

クローンの場所: 簡単なGUIを実装
しているファイル
 ビルド情報をAntに渡す
 Antの処理状況の閲覧

クローンが実装している機能:
 イベントがどこで起こったかを判定している
if文
 イベントのソースに応じて処理を変更
 GUIの部品を作成しているメソッド
 一つの部品につき,一つのメソッドが存在
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験
STEP1:大まかな把握(Cの部分)

クローンの場所: ClearCaseの
各機能を実装しているファイル
 Checkin,
 Checkout,
 Update,

ファイルの特定の部分ではなく,
ほぼ全体がクローンになっていた
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験
STEP2A:要素数の多いクローンセット


予めRNRを用いて,その値が0.5未満のクローンセットは除外
最も要素数の多いクローンセット
 要素数:31個
 クローンの場所:
簡単なGUIを実装しているファイル
 クローンが実装している機能:GUIの部品を生成しているメソッド
 大まかな把握(Bの部分)のクローンの一部
} catch (Throwable iExc) {
handleException(iExc);
}
}
return iAboutCommandPanel;
}
private Label getAboutContactLabel() {
if (iAboutContactLabel == null) {
try {
iAboutContactLabel = new Label();
iAboutContactLabel.setName("AboutContactLabel");
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験
STEP2B:トークン数の多いクローンセット


予めRNRを用いて,その値が0.5未満のクローンセットは除外
最もトークン数の多いクローンセット
 クローンの大きさ:282トークン(77行)
 クローンの場所:WebLogicとWebShereのタスクを定義しているファイル
 クローンが実装している機能:メソッド
isRebuildRequired(引数で与え
られたJarファイルがリビルドする必要があるかどうかを判断)
 一部の使用変数,メソッド名が異なる
 インデント,空行,コメントなど他のコードスタイルが全く同じ
 コピーアンドペーストによる作成を示唆
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
適用実験
STEP2C:多くのファイルを巻き込んでいるクローンセット


予めRNRを用いて,その値が0.5未満のクローンセットは除外
最も多くのファイルを巻き込んでいるクローンセット
 巻き込んでいるファイル数:19ファイル
 クローンの場所:さまざまなファイル
 クローンが実装している機能:連続したアクセサ
 Antだからではなく,Java言語で記述されているから存在しているクローン

このクローンセットに限らず,多くのファイルを巻き込んでいるクローンセッ
トの多くが,Java言語で記述されていることがその存在理由と思われた
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
まとめ

Geminiのビューの特徴をまとめた
 クローン散布図
 メトリクスグラフ
効果的と思われる分析方法の提案を行った
 オープンソースのソフトウェアの対して実験を行った

 コピーアンドペーストによる生成と思われるもの,プログラミング
言語に依存したものなど,さまざまなコードクローンが検出され
た
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
メトリクスRNR(S)について

トークン列 <x a b c a b c a b c y> を考える
 繰り返しは

<x a b c a b c* a* b* c* y> と判定
なぜ <x a b c a* b* c* a* b* c* y> ではないのか?
 前者の方がどちらかというと適切であると思われるから
理論的な裏づけがあるわけではない

繰り返し部分をコードクローンとして検出する場合
 1つ目のクローンコードはできるだけ非繰り返しとしたい
 2つ目以降のクローンコードはできるだけ繰り返しとしたい
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
メトリクスRNR(S)について

[a, b, c]がクローンコードである場合
 <x
a b c a b c* a* b* c* y>は
<x a b c a b c* a* b* c* y> (非繰り返し度 = 3/3)
<x a b c a b c* a* b* c* y> (非繰り返し度 = 1/3)
<x a b c a b c* a* b* c* y> (非繰り返し度 = 0/3)
 <x
a b c a* b* c* a* b* c* y>は
<x a b c a* b* c* a* b* c* y> (非繰り返し度 = 3/3)
<x a b c a* b* c* a* b* c* y> (非繰り返し度 = 0/3)
<x a b c a* b* c* a* b* c* y> (非繰り返し度 = 0/3)
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
メトリクスRNR(S)について

[b, c, a]がクローンコードである場合
 <x
a b c a b c* a* b* c* y>は
<x a b c a b c* a* b* c* y> (非繰り返し度 = 3/3)
<x a b c a b c* a* b* c* y> (非繰り返し度 = 1/3)
 <x
a b c a* b* c* a* b* c* y>は
<x a b c a* b* c* a* b* c* y> (非繰り返し度 = 2/3)
<x a b c a* b* c* a* b* c* y> (非繰り返し度 = 0/3)
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
メトリクスRNR(S)について

[a, b, c, a, b, c]がクローンコードである場合
 <x
a b c a b c* a* b* c* y>は
<x a b c a b c* a* b* c* y> (非繰り返し度 = 5/6)
<x a b c a b c* a* b* c* y> (非繰り返し度 = 2/6)
 <x
a b c a* b* c* a* b* c* y>は
<x a b c a* b* c* a* b* c* y> (非繰り返し度 = 3/6)
<x a b c a* b* c* a* b* c* y> (非繰り返し度 = 0/6)
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University