コードクローン分析ツール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
© Copyright 2025 ExpyDoc