コードクローンの分布情報を用いた特徴抽出手法の提案

Slides:



Advertisements
Similar presentations
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 保守支援を目的とした コードクローン情報検索ツール.
Advertisements

シーケンス図の生成のための実行履歴圧縮手法
TF-IDF法とLSHアルゴリズムを用いた 関数単位のコードクローン検出法
AGMアルゴリズムを用いた ギャップを含むコードクローン情報の生成
情報伝播によるオブジェクト指向プログラム理解支援の提案
アクセス修飾子過剰性の変遷に着目したJavaプログラム部品の分析
剽窃 他人の作品や論文を盗んで,自分のものとして発表すること. プログラムが剽窃される事例もある. Aさんのプログラム Xさんのプログラム
研究の背景 コードクローン ソースコード中に存在する一致または類似したコード片
リファクタリングのための 変更波及解析を利用した テスト支援ツールの提案
プログラム変更支援を目的とした コードクローン情報付加手法の提案と実装
川口真司 松下誠 井上克郎 大阪大学大学院情報科学研究科
プログラム実行履歴を用いたトランザクションファンクション抽出手法
アイテムセットマイニングを利用した コードクローン分析作業の効率向上
コードクローン検出技術と その利用法 神谷年洋‡, 植田泰士†, 肥後芳樹†, 楠本真二†, 井上克郎†
ソースコードの変更履歴における メトリクス値の変化を用いた ソフトウェアの特性分析
コードクローン分析ツールGeminiを用いたコードクローン分析手順
ギャップを含むコードクローンの フィルタリング手法の提案
ソースコードの同時修正支援における関数クローン検出ツールの有効性調査
コードクローンに含まれるメソッド呼び出しの 変更度合の分析
コードクローンに含まれるメソッド呼び出しの 変更度合の調査
識別子の共起関係に基づく類似コード検索法の提案と 欠陥検出への適用
ソードコードの編集に基づいた コードクローンの分類とその分析システム
コードクローンの集約によるリファクタリング支援システムの提案と実装
オブジェクト指向プログラミング言語に対応した コードクローン検出技法の提案と実験
コードクローンの分類に基づいた メソッド引き上げ手順の提案とその有効性評価
動的依存グラフの3-gramを用いた 実行トレースの比較手法
利用関係に基づく類似度を用いたJavaコンポーネント分類ツールの作成
クローンセットに対する主要編集者の分析法の提案と調査
重複コードと非重複コードにおける 修正頻度の比較
クローン検出ツールを用いた ソースコード分析ツールの試作
コードクローン検出ツールを用いた ソースコード分析システムの試作と プログラミング演習への適用
リファクタリング支援のための コードクローンに含まれる識別子の対応関係分析
ソースコードの特徴量を用いた機械学習による メソッド抽出リファクタリング推薦手法
コードクローンの動作を比較するためのコードクローン周辺コードの解析
コードクローンに対する一貫性のない変更に起因する欠陥の検出
Token Comparison Approach to Detect Code Clone-related Bugs
柔軟に変更可能な字句解析機構を持つ コードクローン検出ツールの開発
UMLモデルを対象とした リファクタリング候補検出の試み
プログラム実行履歴を用いたコードクローン検出手法
コードクローン検出に基づくデザイン パターン適用支援手法の提案と実現
プログラム理解におけるThin sliceの 統計的調査による有用性評価
バイトコードを単位とするJavaスライスシステムの試作
コードクローン編集者数に着目した開発履歴の分析
グラフマイニングアルゴリズムを用いた ギャップを含むクローン抽出手法の提案
コードクローンのメトリクス値と 開発者の相関の調査
Geminiを用いた効果的なコードクローン分析方法
○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学
ソフトウェア保守のための コードクローン情報検索ツール
コードクローンの理解支援を目的としたコードクローン周辺コードの解析
コードクローン分類の詳細化に基づく 集約パターンの提案と評価
コーディングパターンの あいまい検索の提案と実装
コードクローン間の依存関係に基づく リファクタリング支援環境の実装
コードクローンの分布情報を用いた特徴抽出手法の提案
メトリクス値の変化に基づく コードクローンの編集傾向分析
プログラムスライスを用いた凝集度メトリクスに基づく 類似メソッド集約候補の順位付け手法
大阪大学 大学院情報科学研究科 コンピュータサイエンス専攻 井上研究室
保守請負時を対象とした 労力見積のためのメトリクスの提案
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
クローン検出ツールを用いた ソフトウェアシステムの類似度調査
オープンソースソフトウェアに対する コーディングパターン分析の適用
メソッドの同時更新履歴を用いたクラスの機能別分類法
蓄積されたオブジェクトの動作履歴を用いた 実行履歴削減手法の提案
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
欠陥検出を目的とした類似コード検索法 吉田則裕,石尾隆,松下誠,井上克郎 大阪大学 大学院情報科学研究科
コードクローン解析に基づく デザインパターン適用候補の検出手法
Geminiを用いた効果的なコードクローン分析方法
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
識別子の読解を目的とした名詞辞書の作成方法の一試案
コードクローンを対象とした リファクタリングの有効性に関する調査
Presentation transcript:

コードクローンの分布情報を用いた特徴抽出手法の提案   大阪大学 大学院情報科学研究科 服部 剛之,肥後芳樹,楠本真二,井上克郎 コードクローンの分布情報を用いた特徴抽出手法の提案というタイトルで, 大阪大学大学院情報科学研究科の服部が発表を行わせていただきます.

コードクローン ソースコード中に存在する同一,もしくは類似したコード片を同一システム中に持つコード片 (以降単にクローンと呼ぶ) コピーアンドペースト等により生成される ソフトウェア保守を困難にする コードの変更が必要な場合 バグ修正,機能追加 保守作業の手間が増大 クローンペア まず,始めにコードクローンとは,ソースコード中に存在する同一, もしくは類似したコード片を同一システム中に持つコード片のことを 指します.以降,単にクローンと呼びます. クローンは主にコピーアンドペーストなどによって生成されます. この図は,2つのファイル中にクローンが存在している例で, 色のついた部分はそれぞれお互いにクローンになっている ことを表しています. このように互いにクローンになっているのをまとめて1つの クローンセットと呼びます. 例えば,クローンが含まれている箇所に バグ修正や機能追加のようなコード変更を行う場合, すべてのクローンにおいてコード変更の検討を行うことが 必要になってきます. このようにクローンが存在すると保守作業の手間が増大します. ゆえに,クローンはソフトウェア保守を困難にする原因となっています. クローンセット

CCFinder,Gemini クローンを対象とした保守支援ツール 国内外の個人・組織に配布 検出ツール: CCFinder[1] 研究機関での利用 企業での商用ソフトウェア開発プロセスへの導入 配布先からのフィードバックを得ている 我々の研究室では,クローンを対象とした保守支援ツールとして, 検出ツールのCCFinder,分析環境の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.

コードクローン検出ツール CCFinder ソースコードをトークン単位で直接比較することによりコードクローンを検出 名前空間の正規化 ユーザ定義名の置き換え テーブル初期化部分の取り除き モジュールの区切りの認識 数百万行規模でも実用的な時間で解析可能 様々なプログラミング言語に対応

CCFinder(処理概要) 1. static void foo() throws RESyntaxException { Source files 字句解析 変換処理 トークン列 検出処理 変換後トークン列 クローン情報 出力整形処理 クローンペア位置情報 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. } 字句解析 変換処理 トークン列 検出処理 変換後トークン列 クローン情報 出力整形処理 字句解析 変換処理 トークン列 検出処理 変換後トークン列 クローン情報 出力整形処理 字句解析 変換処理 トークン列 検出処理 変換後トークン列 クローン情報 出力整形処理 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. } 次にCCFinderの処理概要について簡単に説明します. まず,CCFinderは与えられたソースコードを字句解析し,トークン単位に分割します. 次に,変換処理を行います. 変換処理ではテーブル初期化部分の正規化,ユーザ定義の変数名,メソッド名の正規化などが行われます. そして,この変換後のトークン列に対してサフィックスツリーアルゴリズムを用いて一致部分の検出を行います. この例では,この赤の下線と青の下線の部分が一致部分として検出されました. そして,最後に検出した部分を実際のソースコードにマッピングさせます. CCFinderはこのような処理を行うことでソースコード中の類似部分を検出しています.

コードクローン分析環境 Gemini CCFinderの解析結果を読み込み,クローン情報を視覚的に表示 クローン散布図(スキャタープロット図) メトリクスグラフ CCFinderの解析結果はテキストファイルなので,このまま分析に用いるのは効率的ではない. Geminiを用いて分析をする. GeminiはCCFinderの解析結果ファイルを読み込みこれらの図を用いてコードクローンを視覚的に表示

クローン散布図 ファイルA ファイルB トークン列 a b c d e b c d f b ファイルA 次に Geminiではクローンの位置情報を基にクローン散布図を作成します. クローン散布図を用いることによりユーザがクローンの分布状況を理解する手助けとなります. この図はクローン散布図の例です. 縦軸,横軸は共にソースファイルの並びを表しています. また,ファイル中のトークンも表示しています. この図で点がプロットされている箇所はトークンが一致した箇所を示しています. この図の対角線上では同じ位置のトークンを比較しているため, すべての点がプロットされることになります. また,点の分布は対角線に対して線対称となっています. クローンはある一定以上の長さを持った線分として出現 ファイルB クローン

フィードバックから得られた情報 クローン情報の利用法 問題点 調査すべきクローンをうまく特定したい リファクタリング支援 互いにクローンになっているものを1つにまとめる 設計情報との一貫性確認 設計上説明できるクローンであるか 問題点 検出されたクローンの数が多すぎてどれをみるべきかわからない 調査の必要がないクローン(定型処理など)が含まれている 調査すべきクローンをうまく特定したい フィードバックによって,クローン情報が リファクタリング支援や,設計情報との 一貫性の確認に用いられていることが わかりました. また,ツールから得られたクローン情報を利用する上での問題点として 次の2点がわかりました. 1点目は,検出されたクローンの数が多すぎて どれをみるべきかわからない,というものです. 2点目は,調査の関心がないクローン,例えば 定型処理のようなクローンが含まれているために, どのクローンから見ていけばいいのかわからない, というものです. これらの問題は,クローンの特徴を知ることができれば解決 できると考えられます.

目的とアプローチ 目的: クローン分析の効率化 アプローチ: メトリクスを用いてクローンを分類 クローンを特徴付けして分類し,分類に応じた対策方法を提示する アプローチ: メトリクスを用いてクローンを分類 以下のメトリクスを用いる RAD: クローン間の遠さの尺度 NIF: クローンが存在するファイルの数 本研究では,クローン分析を効率化するために, 調査の必要がないクローンをフィルタします. そこで,これらのメトリクスを用いて クローンを分類する手法を提案します. RADというのはクローン間の遠さの尺度, NIFというのはクローンが存在するファイルの数 を表しています. 次にこれらのメトリクスの詳細について説明します.

RAD: クローン間の遠さの尺度 RAD: 与えられたクローンセットの各要素を含むファイルから共通の親ディレクトリまでの距離の最大値 2 1 最大値を表しています. 例えば,左の図では, ファイルAとファイルBのどちらのファイルからも 共通の親ディレクトリまでの距離は1となるので, RADの値は1となります. 次に右の図の場合では, このクローンセットにおいて,全体の共通の親ディレクトリは,ここになります. よって,RADの値は,全体の共通の親ディレクトリまでの 距離の最大値である2となります. ファイルC ファイルA ファイルB は,クローンを表す ファイルA ファイルB

NIF: クローンが存在するファイルの数 NIF: 与えられたクローンセットの各要素を含むファイルの数 2 3 例:NIF = 2 ファイルC ファイルA 次にNIFというのは与えられたクローンセットの 各要素を含むファイルの数を表します. 例えば,左の図では,2つのファイルにクローンが 含まれているのでNIF = 2となります. 右の図では,3つのファイルにクローンが 含まれているのでNIF = 3となります. ファイルB 2 ファイルA ファイルB 3 は,クローンを表す

クローンの分布に着目した分類方法 RAD,NIFは,クローンの分布の特徴を表すメトリクス 値の高低により,クローンを4つに分類する RAD 高 vertical global RAD,NIFは,クローンの分布の特徴を表すメトリクスです. 本研究ではこれらのメトリクスの高低によりクローンを分類します. ここでは,図のように4つに 分類することにしました. 次にそれぞれの分類について説明します. local horizontal 低 低 高 NIF

分類: local クローンセットに含まれるクローンがディレクトリ階層上近い少数のファイルに存在する vertical global RAD 高 vertical global 分類localでは, クローンセットに含まれるクローンがディレクトリ階層上近い 少数のファイルに存在しています. この図では,1つのファイル中に繰り返し存在するクローンを表しています. 例として,局所的な処理が繰り返されている場合が挙げられます. local horizontal 低 は,クローンを表す 低 高 NIF

分類: horizontal クローンセットに含まれるクローンがディレクトリ階層上近い多数のファイルに存在する vertical RAD 高 vertical global 次に分類horizontalでは, クローンセットに含まれるクローンがディレクトリ階層上近い 多数のファイルに存在しています. この図では,1つのディレクトリ下のファイルにクローンが分散していることを表しています. 例として,ディレクトリ下のファイルがあるシステムの各機能の実装を担当している場合が 挙げられます. local horizontal 低 は,クローンを表す 低 高 NIF

分類: vertical クローンセットに含まれるクローンがディレクトリ階層上遠い少数のファイルに存在する vertical global RAD 高 vertical global 次に分類verticalでは, クローンセットに含まれるクローンがディレクトリ階層上遠い 少数のファイルに存在しています. この図では,クローンが含まれているファイルこそ少ないものの, クローン間の位置関係が遠く離れている状態を表しています. local horizontal 低 低 高 NIF は,クローンを表す

分類: global クローンセットに含まれるクローンがディレクトリ階層上遠い多数のファイルに存在する vertical global RAD 高 vertical global 最後に分類globalでは,クローンセットに含まれるクローンが ディレクトリ階層上遠い多数のファイルに存在しています. この図では,クローンがシステム広範囲に渡って存在している状態を表しています. local horizontal 低 低 高 NIF は,クローンを表す

適用実験 Ant 総ファイル数: 954個 総クローンセット数: 1643個 目的: RAD,NIFに着目して各分類に含まれるクローンの特徴を調べる Java,C,C++で書かれたオープンソースソフトウェアについて分類を行った CCFinderにより検出された30トークン以上のクローンセットを対象 人の手によって確認 Java(4つ): Ant,Webmail,httpunit,Art of Illusion C(2つ)  : Small Device C Compiler,Sketch C++ (2つ): CppUnit,SWIG 総ファイル数: 2948個 総クローンセット数: 14874個 Ant 総ファイル数: 954個 総クローンセット数: 1643個 そして,RAD,NIFの分布に着目して各分類含まれるクローンの特徴を調べる ために以下のような実験を行いました. Java,C,C++(プラスプラス)で書かれたオープンソースソフトウェアについて 分類を行いました. 今回はCCFinderにより検出された30トークン以上のクローンセットを 調査対象としました.30トークン以上というのは,これまでの調査の経験に基づく値です. そして,各分類に含まれるクローンの特徴を人の手によって確認しました. 実験に用いたオープンソースソフトウェアは, Javaのプログラムはこれら4つ, Cのプログラムはこれら2つ, C++のプログラムはこれら2つです. これら8つのプログラムの総ファイル数は2948個, 30トークン以上の総クローンセット数は14874個でした. 今回時間の都合上,ここではAntに行った実験について 説明します.Antの規模は,ソースファイル数954個, 30トークン以上クローンセット数は1643個でした.

クローンの特徴を表す指標 クローンが含まれる関数の名前を用いて指標を定義する クローンがどのような関数に存在するかで分類 same: 同じ名前の関数内に存在するクローン similar: 名前の似た関数内に存在するクローン 名前が似ている: 関数名の一部に共通した単語を持つ 例) addConfiguredInputMapper addConfiguredOutputMapper addConfiguredErrorMapper different: 名前が全く異なる関数内に存在するクローン クローンセットが各指標に該当するか調べることで分類の特徴を評価する 複数の指標に該当することを許す クローンが含まれる関数の名前を用いて same,similar,differentの3つの指標を定義しました. これらの指標はクローンがどのような関数に存在するかで 分類しています. sameというのは,同じ名前の関数内に存在するクローンを表します. 次にsimilarというのは,名前の似た関数内に存在するクローンを表しています. ここでいう名前の似た関数というのは,この例のように関数名の一部に 共通した単語を持つ関数とします. 最後にdifferentというのは,異なる関数内に存在するクローンを表しています. クローンセットが各指標に該当するか調べることで 分類したカテゴリを評価します. 1つのクローンセットが複数の指標に該当することを許します. 次にこの指標を用いた評価条件について説明します.

評価条件 RAD,NIFの高低の閾値はそれぞれの最大値の半分とした 各分類内でメトリクスRNRについて分割 分類に属するクローンの特徴を詳しく調査 RNRについては次のように分割した RNR低: 0 ≦ RNR ≦ 0.3 RNR中: 0.3 < RNR ≦ 0.7 RNR高: 0.7 < RNR ≦ 1 低 中 高 カテゴリ分けでのRAD,NIFの高低の閾値はそれぞれの 最大値の半分としました. また,RNRについては閾値を0.3,0.7として 低中高の3つに分割しました.

RNR: クローン内の重複した処理の 少なさの度合い ∑ Tokensrepeated(c) RNR = 1 - c ∈ S ∑ S: クローンセット c: クローンセットの要素 Tokensall(c) c ∈ S Tokensall(c) : クローンc中の総トークン数 Tokensrepeated(c) : クローンc中の繰り返し部分のトークン数 8トークン RNRというのはこのような式で表されます. これは,クローンセットの各要素であるクローン中に 繰り返しでない部分が存在する割合の平均値をとっています. RNRが小さいほど,クローン中に繰り返しが多く存在する ことになります. 次にTokens allとTokens repeatedについて説明します. 例えば,このようなトークン列の場合, 全体で8トークンなので,Tokens all = 8となります. このトークン列の繰り返し部分に着目すると 4トークン分繰り返しが存在するので, Tokens repeated = 4となります Tokensall = 8 X A B A B A B Y Tokensrepeated = 4 4トークン 直前の繰り返し

繰り返しの定義に対する説明 X A B A B A B Y  8トークン 正規表現のメタ文字“+”を用いて表す X (A B)+ Y  4トークン コード片中の繰り返しの割合: 4 / 8 = 0.5

RNRに着目した特徴 RNRの低いクローンは単純なロジックのクローンであった(繰り返しの多いクローン) 全体が1つのクローン 直前の繰り返し public static String getMethodAccess(int access_flags) { StringBuffer sb = new StringBuffer(); if (isPublic(access_flags)) { sb.append("public "); } else if (isPrivate(access_flags)) { sb.append("private "); } else if (isProtected(access_flags)) { sb.append("protected "); } if (isFinal(access_flags)) { sb.append("final "); if (isStatic(access_flags)) { sb.append("static "); if (isSynchronized(access_flags)) { sb.append("synchronized "); 全体が1つのクローン まず,どのカテゴリにも共通した特徴として, RNRの低いクローンは単純なロジックのクローンが 見られました. これがRNRの低いクローンの例です. 色のついた部分がCCFinderで検出された1つクローンを 表しています. このクローンを見ると同じ内容の命令が繰り返されて いることがわかります. ソースコード自体はfinalやstaticなどの属性を設定する命令となっています. 直前の繰り返し

Antでのクローンセットの分布 要素数が3以上のクローンセットについて調べた(検出されたクローンセットの約35%) vertical 33個 RAD 高 vertical 33個 global 7個 local 530個 horizontal 11個 低 低 高 NIF 要素数が3以上のクローンセットについて調べた(検出されたクローンセットの約35%) Antでのクローンセットの分布は図のようになります. このデータは,要素数が3以上のクローンセットについて 調べた分布です.これは全体のクローンセットに約35%にあたります. この図を見ると分類localに属するクローンセットが大部分を占めていることがわかります.

分類: local の結果 same,similarに該当するクローンが多い あるデータ構造の要素に対して処理を行う各関数内にクローンが見られた 同じデータ構造を用いている カテゴリlocalでの各指標に該当するクローンの 割合はこのようになります. このグラフを見るとsame,similarに該当するクローンが多い ことがわかります. このカテゴリに属するクローンは,あるデータ構造の要素に対して処理を 行う各メソッド内に見られました. 同じデータ構造を用いているのでコードが似ていると言えます.

分類: localに属するクローンの例 同じクローンセットに含まれる関数の例として, getConstantEntry public int getClassEntry(String className) { int index = -1; for (int i = 0; i < entries.size() && index == -1; ++i) { Object element = entries.elementAt(i); if (element instanceof ClassCPInfo) { ClassCPInfo classinfo = (ClassCPInfo) element; if (classinfo.getClassName().equals(className)) { index = i; } return index; 同じクローンセットに含まれる関数の例として, getConstantEntry getMethodRefEntry などが存在した これがカテゴリlocalに属するクローンの例です. 色のついた部分がクローンを表しています. このクローンが含まれるクローンセットでは, getConstantEntryやgetMethodEntryのような エントリを取得するメソッド内にクローン が見られました. このことから同じデータ構造を用いて いるのでコードが似ていることが言えます. クローンの内容はエントリから特定の要素を取り出すといった処理であり, 同じクローンセットに含まれる関数の例を見るとある要素を取得すると いった関数であるため,クローンとなっていると考えられます.

分類: horizontal の結果 sameに該当するクローンが多い 他のプログラムを実行する関数内にクローンが見られた 関数名は同じであるがシグネチャが異なる 次にカテゴリhorizontalでの各指標に該当するクローンの 割合はこのようになります. グラフを見るとsameに該当するクローンが多いことがわかります. このカテゴリに属するクローンは,例えば他のプログラムを実行する メソッドに見られました. 引数ごとに異なるメソッドとして実装されているといえます.

分類: horizontalに属するクローンの例 public void execute() throws BuildException { Commandline commandLine = new Commandline(); Project aProj = getProject(); int result = 0; if (getViewPath() == null) { setViewPath(aProj.getBaseDir().getPath()); } commandLine.setExecutable(getClearToolCommand()); commandLine.createArgument().setValue(COMMAND_CHECKIN); checkOptions(commandLine); if (!getFailOnErr()) { getProject().log("Ignoring any errors that occur for: " + getViewPathBasename(),Project.MSG_VERBOSE); result = run(commandLine); if (Execute.isFailure(result) && getFailOnErr()) { String msg = "Failed executing: " + commandLine.toString(); throw new BuildException(msg, getLocation()); 外部プログラムの各機能を呼び出す関数中に クローンが存在した これがカテゴリhorizontalに属するクローンの例です. 色のついた部分がクローンを表しています. このクローンが含まれるクローンセットでは, ある外部プログラムの各機能を呼び出すメソッド中にクローンが 見られました. そのクローンは,ある親クラスの11個の子クラスがそれぞれ同名のメソッドを定義していました.

分類: vertical の結果 differentに該当するクローンが多い 類似した構造のパッケージにクローンが見られた 割合はこのようになります. グラフを見るとdifferentに該当するクローンが多いことがわかります. このカテゴリに属するクローンは類似した構造のパッケージに見られました.

分類: vertical に属するクローンの例 while (classEnum.hasMoreElements()) { String className = (String) classEnum.nextElement(); log(" Class " + className + " affects:", Project.MSG_DEBUG); Hashtable affectedClasses = (Hashtable) affectedClassMap.get(className); Enumeration affectedClassEnum = affectedClasses.keys(); while (affectedClassEnum.hasMoreElements()) { String affectedClass = (String)   affectedClassEnum.nextElement(); ClassFileInfo info = (ClassFileInfo) affectedClasses.get(affectedClass); log(" " + affectedClass + " in " + info.absoluteFile.getPath(), } main testcases ant ant taskdefs taskdefs これがカテゴリverticalに見られたクローンの例です. この例では, 上位の階層で異なるパッケージに分けられているものの, それぞれのパッケージの階層がよく似た構造を 持ったファイル内にクローンが見られました. クローンとなっている箇所は要素を取り出して,それに関連する情報を取得するというものである.

分類: global の結果 differentに該当するクローンがほとんどである 定型処理に該当するクローンが見られた 割合はこのようになります. グラフを見るとdifferentに該当するクローンがほとんどであることがわかります. このカテゴリに属するクローンは定型処理ばかりでした.

分類: global に属するクローンの例 クローンが存在している関数は ストリームを閉じる処理を2回続けて 行う内容であった } catch (IOException ioex) { throw new BuildException("Error while concatenating: " + ioex.getMessage(), ioex); } finally { if (reader != null) { try { reader.close(); } catch (IOException ignore) { // ignore } if (os != null) { os.close(); クローンが存在している関数は ストリームを閉じる処理を2回続けて 行う内容であった これがカテゴリglobalに属するクローンの例です. 色のついた部分がクローンを表しています. このクローンが含まれるクローンセットは, 2つのストリームを続けて閉じる処理で構成されていました. Antでは2つのストリームを同時に使うことが多く, Antにおける定型処理であると言えます.

考察 他のパッケージからのアドホックなコピーの恐れ 異なるソフトウェアでも,同じ分類に属するクローンに同じ特徴が見られた ソフトウェアの記述言語を問わない メトリクス値に基づいてクローンの特徴を抽出可能 各分類の特徴を利用することでクローンをフィルタすることができる 例1) globalに属するクローンは定型処理であるので,リファクタリング対象にならない 例2) verticalに属するクローンは設計情報との一貫性を確認することが有益 他のパッケージからのアドホックなコピーの恐れ 例3) RNRが低いクローンは単純なロジックの繰り返しであるので利用しにくい 単純な代入文の連続など リファクタリングの対象にならない 先ほど,Antについて各カテゴリの特徴について説明しましたが, 異なるソフトウェアでも同じ特徴が見られました. このことからソフトウェアの記述言語を問わず, メトリクス値に基づいてクローンの特徴を抽出することが可能であるといえます. そして,各カテゴリの特徴を利用することでクローンをフィルタする ことが可能であると言えます. 1つ目の例として,カテゴリglobalに属するクローンは定型処理であるので, リファクタリングの対象からはずす事ができます. 2つ目の例として,カテゴリverticalに属するクローンは,他のパッケージからの アドホックなコピーの恐れが考えられ,設計情報との一貫性を 確認することが有益ではないかと開発者が判断できます. また,RNRの低いクローンは,繰り返しで構成された単純なロジックのクローン であるので,リファクタリングの対象からはずすことができます.

まとめと今後の課題 まとめ 今後の課題 コードクローン分析の効率化を支援するコードクローンの特徴抽出手法の提案と評価 分類の詳細化 ツールとしての実装 実際の開発現場での適用実験と評価 最後にまとめと今後の課題です. コードクローン分析を支援するコードクローンの 特徴抽出手法の提案と評価を行いました. 今後の課題として,分類の詳細化や ツールとしての実装,実際の開発現場で適用することが 挙げられます. 以上で発表を終わります. ありがとうございました.