コードクローン統合分析ツール ICCA 肥後 芳樹† ,吉田 則裕† ,神谷 年洋‡,楠本 真二† ,井上 克郎†

Slides:



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

背景 ソフトウェアの大規模化・複雑化 生産性と品質の向上 ↓ オブジェクト指向分析設計の適用 開発ツールの投入.
AGMアルゴリズムを用いた ギャップを含むコードクローン情報の生成
情報伝播によるオブジェクト指向プログラム理解支援の提案
Object Group ANalizer Graduate School of Information Science and Technology, Osaka University OGAN visualizes representative interactions between a pair.
剽窃 他人の作品や論文を盗んで,自分のものとして発表すること. プログラムが剽窃される事例もある. Aさんのプログラム Xさんのプログラム
リファクタリングのための 変更波及解析を利用した テスト支援ツールの提案
プログラム変更支援を目的とした コードクローン情報付加手法の提案と実装
川口真司 松下誠 井上克郎 大阪大学大学院情報科学研究科
ソースコードに対する適用可能な修正手順を 可視化するリファクタリング支援手法の提案
CKメトリクスを用いてリファクタリングの 効果を予測する手法の提案
プログラム実行履歴を用いたトランザクションファンクション抽出手法
アイテムセットマイニングを利用した コードクローン分析作業の効率向上
プログラム実行時情報を用いたトランザクションファンクション抽出手法
大規模ソースコード集合を対象とした 類似関数集合群の抽出
コードクローン検出技術と その利用法 神谷年洋‡, 植田泰士†, 肥後芳樹†, 楠本真二†, 井上克郎†
ソースコードの変更履歴における メトリクス値の変化を用いた ソフトウェアの特性分析
コードクローン分析ツールGeminiを用いたコードクローン分析手順
コードクローンの分布情報を用いた特徴抽出手法の提案
ギャップを含むコードクローンの フィルタリング手法の提案
コードクローンに含まれるメソッド呼び出しの 変更度合の分析
コードクローンに含まれるメソッド呼び出しの 変更度合の調査
ソードコードの編集に基づいた コードクローンの分類とその分析システム
コードクローンの集約によるリファクタリング支援システムの提案と実装
オブジェクト指向プログラミング言語に対応した コードクローン検出技法の提案と実験
暗黙的に型付けされる構造体の Java言語への導入
コードクローンの分類に基づいた メソッド引き上げ手順の提案とその有効性評価
オブジェクト指向プログラムにおける エイリアス解析手法の提案と実現
CKメトリクスに基づくリファクタリングの 効果予測手法の提案と実装
ソフトウェアメトリクスと メソッド内の構造を用いた リファクタリング支援手法の提案
利用関係に基づく類似度を用いたJavaコンポーネント分類ツールの作成
クローンセットに対する主要編集者の分析法の提案と調査
Javaプログラムの変更を支援する 影響波及解析システム
クローン検出ツールを用いた ソースコード分析ツールの試作
コードクローン検出ツールを用いた ソースコード分析システムの試作と プログラミング演習への適用
リファクタリング支援のための コードクローンに含まれる識別子の対応関係分析
ソースコードの特徴量を用いた機械学習による メソッド抽出リファクタリング推薦手法
コードクローンの動作を比較するためのコードクローン周辺コードの解析
UMLモデルを対象とした リファクタリング候補検出の試み
プログラム実行履歴を用いたコードクローン検出手法
コードクローン検出に基づくデザイン パターン適用支援手法の提案と実現
コードクローン編集者数に着目した開発履歴の分析
コード片に共通した特性を自動抽出する ソースコード閲覧ツールの試作
Geminiを用いた効果的なコードクローン分析方法
○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学
ソフトウェア保守のための コードクローン情報検索ツール
コードクローンの理解支援を目的としたコードクローン周辺コードの解析
コードクローン分類の詳細化に基づく 集約パターンの提案と評価
コーディングパターンの あいまい検索の提案と実装
コードクローン間の依存関係に基づく リファクタリング支援環境の実装
コードクローンの分布情報を用いた特徴抽出手法の提案
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
プログラムスライスを用いた凝集度メトリクスに基づく 類似メソッド集約候補の順位付け手法
大阪大学 大学院情報科学研究科 コンピュータサイエンス専攻 井上研究室
保守請負時を対象とした 労力見積のためのメトリクスの提案
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
アスペクト指向言語のための視点に応じた編集を可能にするツール
クローン検出ツールを用いた ソフトウェアシステムの類似度調査
オープンソースソフトウェアに対する コーディングパターン分析の適用
メソッドの同時更新履歴を用いたクラスの機能別分類法
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
欠陥検出を目的とした類似コード検索法 吉田則裕,石尾隆,松下誠,井上克郎 大阪大学 大学院情報科学研究科
エイリアス関係を考慮した Javaプログラム用静的スライシングツール
コードクローン解析に基づく デザインパターン適用候補の検出手法
メソッド抽出リファクタリングが 行われるメソッドの特徴調査
Geminiを用いた効果的なコードクローン分析方法
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
識別子の読解を目的とした名詞辞書の作成方法の一試案
コードクローンを対象とした リファクタリングの有効性に関する調査
Presentation transcript:

コードクローン統合分析ツール ICCA 肥後 芳樹† ,吉田 則裕† ,神谷 年洋‡,楠本 真二† ,井上 克郎† †大阪大学 大学院情報科学研究科 {y-higo, n-yosida, kusumoto, inoue}@ist.osaka-u.ac.jp ‡科学技術振興機構 さきがけ kamiya@ist.osaka-u.ac.jp The title of my talk is “aries: refactoring support environment based on code clone analysis”

ICCA - 概要(1/2) GUI ベースの統合分析ツール CCFinder をコードクローン検出エンジンとして使用 目的別にサブコンポーネントが存在 可視化,理解支援 - Gemini コンポーネント リファクタリング支援 - Aries コンポーネント デバッグ支援 - Libra コンポーネント 実装言語 Java 規模 ファイル数 : 523 総行数 : 約136,000行

ICCA - 概要(2/2) Aries Gemini Libra Software Understanding Software Visualization Refactoring Support Code clone repository Subsystem User Code clone detector (CCFinder) ICCA (Integrated Code Clone Analyzer) Gemini Aries Libra Debug Support

クローンペア と クローンセット クローンペア クローンセット (C1, C4) {C1, C4, C5} (C1, C5) クローンペア: 互いに一致・類似しているコード片の対 クローンセット: 互いに一致・類似しているコード片の集合 以前はクローンクラスと言っていました CCFinder はコードクローンをクローンペアとして検出する CCFinder 配布セットには CCReformer というツールが含まれており,このツールを用いるとクローンペアをクローンセットに変換することができる クローンペア クローンセット (C1, C4) {C1, C4, C5} (C1, C5) {C2, C3} (C2, C3) (C4, C5) C1 C2 C3 C4 では,ここで私たちが用いているコードクローンの語句を紹介したいと思います. まず1つめがクローンペアです. クローンペアとは,互いに類似したコード片の対を表す言葉です. もう1つがクローンセットです. クローンセットとは,互いに類似しているコード片の集合を表す言葉です. 例えば,このソースコードではコード片C1,C4,C5が類似しており,C2とC3 が類似しています. この様な場合,クローンペアは(C1, C4)のペア,(C1, C5)のペア,(C2,C3)のペア,(C4,C5)の4つのペアが存在し, クローンセットは(C1, C4, C5)のセットと(C2,C3)のセットが存在します. CCFinderはクローンペアとしてコードクローンを検出し,そのあとクローンセット形式で出力します. C5

Gemini - 概要 目的 CCFinder の検出したコードクローンの可視化・理解支援 分析の分離 旧 Gemini : 全てのビューが密接に関連 新 Gemini : “クローンベースの分析”と”ファイルベースの分析” スケーラビリティの改善 旧 Gemini : 数万行(検出したクローンの量に依存) 新 Gemini : 数百万行(検出したクローンの量に依存)

Gemini - 分析の分離 旧 Gemini では全てのビューが密接に関連をしている 理解しにくい 分析を “クローンベースの分析” と “ファイルベースの分析” に分離 クローンベースの分析 メトリクスグラフ クローンセットリスト ソースコードビュー ファイルベースの分析 スキャタープロット ファイルリスト グループリスト ディレクトリツリー ソースコードビュー

Gemini - スキャタープロット a b c a b c a d e c a b c a b c a d e c 原点は左上角 水平軸,垂直軸はソースコードのトークン列を表す 黒い点は,両軸の対応したトークンが一致していることを表す 主対角線上では自己比較が行われるため,常に主対角線が描画される CCFinderから検出されてくるようなクローンペアは,対角線分として現れる 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

Gemini - メトリクスグラフ(1/3) メトリクスグラフで用いているメトリクス LEN(S) : クローンセット S に含まれるコード片のトークン数の平均値 POP(S) : S に含まれるコード片の数 DFL(S) : S に含まれる全てのコード片を1つのサブルーチンにマージした場合のトークン減少数の予測値 RAD(S) : S に含まれるコード片がファイルシステム内での分散度 全てのコード片が1つのファイル内に存在 : RAD(S) = 0 全てのコード片が1つのディレクトリ内に存在 : RAD(S) = 1 new sub routine caller statements

Gemini - メトリクスグラフ(2/3) メトリクスの続き RNR(S) : S に含まれるコード片がどの程度”非繰り返し”であるかを表す. 例 : 以下のトークン列を考える このトークン列から,CCFinder はコード片 F1とF2 がクローンになっていると検出する. この時 RNR(S) は以下の式で計算される

Gemini - メトリクスグラフ(3/3) パラレルコーディネーショングラフ 各メトリクス毎に平行座標軸 1つのクローンセットにつき,1本の折れ線を描画 RAD LEN POP DFL RNR 4 3 2 1

Gemini - スケーラビリティの改善 旧 Gemini において著しくスケーラビリティを低下させていたのはスキャタープロット(クローンペアデータ) スキャタープロットの改善 ズーム機能 旧 Gemini : 50倍が限度 新 Gemini : 1つのファイルにまで拡大可能 クローンのレンダリング 旧 Gemini :常に1つのクローンペアにつき,1本の線分を描画 新 Gemini : 状況に応じて,複数のクローンをまとめて描画 なくなった機能 ソーティング機能 旧 Gemini : ファイルID,クローン率などで並び替えが可能 新 Gemini : 並び替えは不可能

Gemini – 分析例(デモンストレーション) クローンベースの分析 1例 ファイルベースの分析 3例

Gemini - クローンベースの分析例 目的 クローンセットをその特徴に基づいて絞込みを行う 解析の流れ(例) メトリクスグラフを用いてクローンセットの絞込み クローンセットリストを用いて,絞り込んだクローンセットのソーティング ソースコードビューを用いて絞り込んだクローンのソースコード閲覧

Gemini - ファイルベースの分析例(1/2) 目的 ファイルをその情報に基づいて絞込みを行う 解析の流れ(例) 例1: ディレクトリツリーから ディレクトリツリーでファイル(またはディレクトリ)を選択 スキャタープロットでクローン分布状態を確認 ソースコードビューでファイルのソースコードを閲覧

Gemini - ファイルベースの分析(2/2) 解析の流れ(続き) 例2: ファイルリストから ファイルリストで定量的な値に基づき,ファイルを選択 選択されたファイルとクローンを共有しているファイルを確認 ソースコードビューで選択されたファイルのソースコードを閲覧 例3: グループリストから グループリストでクローン率が高いグループを選択 選択されたグループに含まれているファイルを確認 選択されたグループと他の各グループとの類似度を確認

Gemini - ファイルメトリクス NOL(f): ファイル f の行数 NOT(f): f のトークン数 NOC(f): f に含まれているコードクローンの数 ROC(f): f がどの程度クローンになっているかを表す 例: ファイル f1 は 200 トークンから成り,そのうちの 100 トークンがコードクローンになっている ROC(f1) = (100 / 200) × 100% = 50% NOF(f): f とクローンを共有しているファイルの数

Gemini – フラグメントリスト コードフラグメントの属性 ファイル内位置 開始行.開始列 - 終了行.終了列 長さ トークン数 分散度(ディレクトリ構造上どの程度広がっているか) Dense: 全てのクローンが同一ファイル内に存在 Middle: 全てのクローンが同一ディレクトリ内に存在 Scattered: クローンはディレクトリをまたがって存在 同形コードフラグメントの数

Gemini – グループメトリクス NOF(g): グループ g に含まれるファイルの数 NOL(g): g に含まれるファイルの行数の和 NOT(g): g に含まれるファイルのトークン数の和 NOC(g): g に含まれるコードクローンの数 ROC(g): g がどの程度クローンになっているかを表す 例1. g1 にはファイル f1 と f2 が含まれている f1 は 200 トークンから成り,そのうちの 20 トークンがクローンと成っている f2 は 300 トークンから成り,そのうちの 80 トークンがクローンと成っている ROC(g1) = (20 + 80) / (200 + 300) ×100% = 20%

Aries - 概要(1/2) 目的 コードクローンの集約(リファクタリング)支援 リファクタリング支援のための処理 理由 CCFinder はコードクローンとトークンの列として検出するために,検出されたコードクローンはリファクタリングに適しているとは言えない 処理内容 CCFinder の検出したクローンから,まとまりのある部分を抽出 抽出部分を,メトリクスを用いて定量的な特徴づけ

Aries - 概要(2/2) 一般的なリファクタリングプロセス リファクタリング箇所の特定 リファクタリング方法の選定 リファクタリング効果の調査 ソースコードの修正 回帰テストの実施 Aries では 1. と 2. をサポート

Aries - リファクタリング箇所の抽出 目的 CCFinder はトークンの列としてコードクローンを検出 検出された全てのコードクローンがリファクタリング可能ではない リファクタリングのできそうな部分を抽出することで,より効率的なリファクタリング支援ができる 抽出箇所 プログラミング言語での構造的なまとまり 例: Java 言語 宣言単位 : クラス宣言, インターフェース宣言 メソッド単位 : メソッド本体,コンストラクタ, 文単位 : do文,for文,if文,switch文,synchronized文,try 文,while文

CCFinder が検出するコードクローン fragment 1 609: reset(); 610: grammar = g; 611: // Lookup make-switch threshold in the grammar generic options 612: 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 options 626: if (grammar.hasOption("codeGenBitsetTestThreshold")) { 627: try { 628: bitsetTestThreshold = grammar.getIntegerOption("codeGenBitsetTestThreshold"); Aries が抽出する部分 CCFinder が検出するコードクローン fragment 2 623: } 624: 625: // Lookup bitset-test threshold in the grammar generic options 626: 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 options 640: if (grammar.hasOption("codeGenDebug")) { 641: Token t = grammar.getOption("codeGenDebug"); 642: if (t.getText().equals("true")) { This is an example of the extraction process. For these fragments, CCFinder detects the highlighted parts as clone pair. In this case, the proposed method extracts these “if statements” because these are the biggest blocks in the clones.

CCFinder が検出するコードクローン fragment 3 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: } CCFinder が検出するコードクローン fragment 4 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: } This is another example. For this source code, CCFinder detects the highlighted parts as a clone pair. But this clone pair includes no structural block, so the proposed method does nothing.

Aries - メトリクスを用いた特徴づけ(1/2) 目的 抽出した部分はメソッドなどのまとまりのあるクローンになっているが,それらがどのようにリファクタリング可能であるかは不明 人が各抽出部分がどのように集約できるかを調査するのは非効率 メトリクスを用いて特徴づけを行い,どのように集約できるかを予測 どのように集約できるか 既存のリファクタリングパターンを用いる

Aries - メトリクスを用いた特徴づけ(2/2) 以下のリファクタリングパターン[1][2]が,コードクローンの集約に用いることができる Extract Class, Extract Method, Extract Super Class, Form Template Method, Move Method, Parameterize Method, Pull Up Constructor, Pull Up Method, Aries は抽出した各クローンに対して,上記のリファクタリングパターンのどれが適しているかを示す [1]: M. Fowler: Refactoring: Improving the Design of Existing Code, Addison-Wesley, 1999. [2]: http://www.refactoring.com/, 2004.

Aries - ボリュームメトリクス(LEN, POP, DFL) メトリクスグラフで用いているメトリクス LEN(S) : S に含まれるコード片のトークン数の平均値 POP(S) : S に含まれるコード片の数 DFL(S) : S に含まれる全てのコード片を1つのサブルーチンにマージした場合のトークン減少数の予測値 new sub routine caller statements

Aries - 結合度メトリクス(NRV, NSV) int a , b, c; … if( … ){ …; … = b + c; a = …; } assignment reference コード片 f1 例: ・クローンセット S1 は f1 と f2 を含んでいる ・コード片 f1 では, 外部定義の変数 b と c に対して参照, a に対して代入を行っている ・コード片 f2 では f1 と同様の処理が行われているとする then,NRV(S) = ( 2 + 2 ) / 2 = 2 NSV(S) = ( 1 + 1 ) / 2 = 1 NRV(S): S に含まれるコード片が,その外部で定義された変数をどの程度参照しているかを表す NSV(S): S に含まれるコード片が,その外部で定義された変数に対してどの程度代入を行っているかを表す 定義 クローンセット S はコード片 f1, f2, ・・・, fn を含んでいる si はコード片 fi の内部で参照されている外部定義変数の数を表す ti はコード片 fi の内部で代入されている外部定義変数の数を表す

Aries - 分散度メトリクス(DCH) DCH(S): S に含まれるコード片がクラス階層において,どの程度広く分散しているかを表す クラス B クラス C コード片 f1  コード片 f2 例 2: ・クローンセット S はコード片 f1 ,f2を含んでいる ・f1 を含むクラスと,f2を含むクラスの直接の親クラスが共通であった場合, DCH(S) = 1 コード片 f1  コード片 f2 class A class B 例 3: ・クローンセット S はコード片 f1 , f2 を含んでいる ・ コード片f1 を含むクラスと コード片f2 を含むクラスが共通の親クラスを持っていない場合, DCH(S) = ∞ 例 1: ・クローンセット S はコード片 f1 ,f2を含んでいる ・コード片f1 を含むクラスとコード片f2を含むクラスが同一であった場合, DCH(S) = 0 クラス A コード片 f1 コード片 f2 DCH(S): S に含まれるコード片がクラス階層において,どの程度広く分散しているかを表す 定義 クローンセット S はコード片 f1, f2, ・・・,fn を含む コード片 fi はクラス Ci 中に存在する クラス Cp は,クラス C1, C2, ・・・,Cn の共通の親クラスのうち,クラス階層的に最も下に位置するクラスを表す D(Ci, Cj) はクラス Ci と クラス Cj のクラス階層内での距離を現す もしクラス C1,C2,・・・,Cn が共通の親クラスを持たない時は DCH(S) は ∞ とする このメトリクスは対象ソフトウェアのクラス階層内のみで計算される

Aries - 分析手順(デモンストレーション) クローンセットの絞込み メトリクスグラフ メトリクス値による絞込み ユニットセレクションチェックボックス 単位による絞込み クローンセットの選択 クローンセットリスト 各メトリクス値に基づいたソーティングが可能 選択したクローンセット情報の取得 クローンセットビューワー コード片のリスト ソースコード コードクローン内で用いている外部定義変数一覧

Aries - 変数の種類 this_class_field 自クラスのフィールド super_class_field 親クラスのフィールド Interface_field インターフェースのフィールド local ローカル変数 outer 外側のクラス内で定義された変数

Libra - 概要 目的 ソースコード修正(デバッグ,機能追加など)の支援 あるコードクローンに対して修正を行うと,それと対応する全てのコードクローンに対して,同様の修正の是非を考慮する必要がある Gemini コンポーネントとの違い ユーザは検出したいコード片を入力 無駄なコードクローンは検出しない

Libra - 検出手法 CCFinder の検出オプションを利用 ファイル内クローン ファイル間クローン グループ間クローン ユーザが入力したコード片をグループ1,対象ソースコードをグループ2として,グループ間クローンのみを検出するオプションをつけて,CCFinder を実行する この検出手法のメリット 検出時間の短縮 CCFinder はコードクローンを検出した後,ソーティングを行ってからコードクローンを出力する 無駄なクローンを検出しないことで,ソーティング時間を短縮できる

Libra - 分析手順(デモンストレーション) コードクローン検出対象ファイルを選択 検出を行うコード片を入力 ディレクトリツリーで,どのファイルにクローンが含まれているのかを確認 ソースコードビューで,ファイルのどの部分がクローンになっているのかを確認

日立システムアンドサービス での適用事例 肥後 芳樹† ,前田憲一‡ †大阪大学 大学院情報科学研究科 y-higo@ist.osaka-u.ac.jp ‡株式会社 日立システムアンドサービス ke-maeda@hitachi-system.co.jp

適用対象 対象ソフトウェア 日立システムアンドサービス(社内システム) 規模 行数: 約7万行 クラス数: 309

コードクローン検出 検出オプション 最小一致トークン数: 50(約10行) 以下のユーザ定義名の正規化は行わない 変数の型 リテラル メソッド名 検出クローンセット数 宣言単位: 4 メソッド単位: 13 文単位: 49

用いたリファクタリングパターン 宣言,メソッド,文単位のクローンセットに対して以下のリファクタリングパターンの適用を試みた. 宣言単位: Extract Super Class クローンとなっているクラスに対して共通の親クラスを作成 共通の機能は親クラスに引き上げ クラスがまったく同一の場合は,1つを残して他は削除 メソッド単位: Move Method ユーティリティクラス等に移動 文単位: Extract Method メソッド内の一部分を新たなメソッドとして抽出

パターン1: Extract Super Class

パターン2: Move Method

パターン3: Extract Method void printOwing() { printBanner(); //print details System.out.println ("name: " + _name); System.out.println ("amount " + getOutstanding()); } printBanner(); printDetails(getOutstanding()); } void printDetails (double outstanding) { System.out.println ("amount " + outstanding);

絞込み条件 Extract Super Class クラス単位のクローンセット 親クラスのメンバを用いていない(NSV,NRV が0) 共通の親クラスがない(DCH が∞) Move Method メソッド本体のクローンセット 現在定義されているクラスのメンバを用いていない(NSV,NRVが0) Extract Method 文単位のクローンセット クローン外部で定義された変数に対しては,高々1つにしか代入を行っていない(NSV が1以下) 全てのクローンが単一のクラス内に存在する(DCHが0) 3つ以上同一のコード片が存在(POPが3以上)

絞込み結果 検出クローンセット数 宣言単位: 4 メソッド単位: 13 文単位: 49 絞込み条件に一致したクローンセット数 Extract super Class: 4 Move Method: 5 Extract Method: 12

評価方法(1/3) 絞り込まれた各クローンセットに対して以下の評価を行って頂いた クローンの現在の状態について( (a),(b)から選択) ソフトウェアのサイズ(※1) ソフトウェアのデザイン(※2) クラスの凝集度(※3) クラス間の結合度(※4) パフォーマンス (a)悪化させている, (b) 影響していない ※1 モジュール(クラスやメソッドなど)のステップ数やトークン数を表す ※2 クラスの階層構造やカプセル化を表す ※3 1つのクラスが責任を持って1つの機能を提供しているかを表す.1つのクラスが複数の事柄を扱っていたり,また特に何も機能を提供していない場合は,凝集度的にみて悪い(低い)ことを表す ※4 他のクラスのフィールドやメソッドを用いていることを表す.フィールドやメソッドが適切なクラスに定義されていないと必要以上に他クラスのフィールドやメソッドを呼び出すことになり,結合度的にみて悪い(高い)ことを表す.

評価方法(2/3) 評価の続き リファクタリングの効果について( (a) (b) (c) (d) から選択) サイズ面 デザイン面 クラスの凝集度の面 クラス間の結合度の面 パフォーマンス面 ソースコードの可読性 ソースコードの再利用性 (a) 改善される,(b) 将来的な問題の予防にはなる, (c) 効果なし,(d) 悪化する

評価方法(3/3) 評価の続き リファクタリングのコストについて((a) (b) (c) から選択) ソースコードの修正 回帰テスト 総合的な評価((a) (b) (c) (d) から選択) このクローンセットは (a) すぐにリファクタリングすべき (b) 将来的にはリファクタリングすべき (c) リファクタリングしてもしなくてもよい (d) リファクタリングすべきではない

評価結果 - Extract Super Class(1/3) (クラス単位の)クローンの現在の状態 全てのクローンセットがサイズとデザインを悪化させていた どのクローンセットも凝集度,結合度,パフォーマンスには影響していなかった (a) 悪化させている (b) 影響していない ソフトウェアのサイズついて 4 ソフトウェアのデザインについて クラスの凝集度について クラス間の結合度について パフォーマンスについて

評価結果 - Extract Super Class(2/3) (クラス単位の)リファクタリングの効果 全てのクローンセットのリファクタリングがサイズ,デザイン,可読性,再利用性の面で有効である どのクローンセットのリファクタリングも凝集度,結合度,パフォーマンス面では効果がない (a) 改善される (b) 将来的な問題の予防にはなる (c) 効果なし (d) 悪化する サイズ 2 デザイン クラスの凝集度 4 クラス間の結合度 パフォーマンス ソースコードの可読性 1 3 ソースコードの再利用性

評価結果 - Extract Super Class(3/3) (クラス単位の)リファクタリングのコスト ソースコードの修正はそれほどコストがかからない 回帰テストは煩雑になる場合がある (クラス単位の)総合的な評価 全てのクローンセットがリファクタリングするべき (a) 非常に煩雑である (b) 少し手間がかかる (c) すぐに完了できる ソースコードの修正は 3 1 回帰テストは 2 (a) すぐにすべき (b) 将来的にはすべき (c) してもしなくてもよい (d) すべきではない リファクタリングを 2

評価結果 - Move Method(1/3) (メソッド単位の)クローンの現在の状態 全てのクローンセットがサイズ,デザインを悪化させていた. 多くのクローンセットが凝集度を悪化させていた リファクタリングすべき箇所を検出できている ほとんどのクローンセットが結合度,パフォーマンスには影響していなかった (a) 悪化させている (b) 影響していない ソフトウェアのサイズついて 5 ソフトウェアのデザインについて クラスの凝集度について 4 1 クラス間の結合度について パフォーマンスについて

評価結果 - Move Method(2/3) (メソッド単位の)リファクタリングの効果 全てのクローンセットのリファクタリングがサイズ,デザイン,凝集度,可読性,再利用性の面で有効である どのクローンセットのリファクタリングも結合度,パフォーマンス面では効果がない (a) 改善される (b) 将来的な問題の予防にはなる (c) 効果なし (d) 悪化する サイズ 5 デザイン クラスの凝集度 クラス間の結合度 パフォーマンス ソースコードの可読性 4 1 ソースコードの再利用性

評価結果 - Move Method(3/3) (メソッド単位の)リファクタリングのコスト ソースコードの修正,回帰テスト共にそれほどコストがかからない (メソッド単位の)総合的な評価 全てのクローンセットがリファクタリングするべき (a) 非常に煩雑である (b) 少し手間がかかる (c) すぐに完了できる ソースコードの修正は 5 回帰テストは (a) すぐにすべき (b) 将来的にはすべき (c ) してもしなくてもよい (d) すべきではない リファクタリングを 4 1

評価結果 ー Extract Method(1/3) (文単位の)クローンの現在の状態 一部のクローンセットがサイズ,デザインを悪化させていた. 全てのクローンセットが凝集度,結合度,パフォーマンスには影響していなかった (a) 悪化させている (b) 影響していない ソフトウェアのサイズついて 2 10 ソフトウェアのデザインについて クラスの凝集度について 12 クラス間の結合度について パフォーマンスについて

評価結果 - (2/3) (文単位の)リファクタリングの効果 サイズ,デザイン,可読性,再利用性は,リファクタリングの効果あり,効果なし,逆効果に分かれた 全てのリファクタリングが凝集度,結合度,パフォーマンスについては効果がなかった (a) 改善される (b) 将来的な問題の予防にはなる (c) 効果なし (d) 悪化する サイズ 5 4 3 デザイン 6 クラスの凝集度 12 クラス間の結合度 パフォーマンス ソースコードの可読性 ソースコードの再利用性 2

評価結果 - (3/3) (文単位の)リファクタリングのコスト 半数のクローンセットが,ソースコード修正・回帰テスト共にコストが大きい (文単位の)総合的な評価 半数のクローンセットがリファクタリングすべきでない (a) 非常に煩雑である (b) 少し手間がかかる (c) すぐに完了できる ソースコードの修正は 4 5 3 回帰テストは 6 2 (a) すぐにすべき (b) 将来的にはすべき (c) してもしなくてもよい (d) すべきではない リファクタリングを 3 6

考察 クラス単位,メソッド単位のクローンセットはリファクタリングすべき 対象のクローンセットはソフトウェアの保守性を悪化させていた リファクタリングにより保守性の改善を期待できる コストがそれほどかからない 文単位のクローンセットはリファクタリングすべきでないものが存在した メソッドの一部分を抽出する作業は煩雑 条件をきつくする 修正支援を行う 用いているフレームワークに依存したクローンセット

CCFinder: Clone Detection Process Source files Lexical analysis Transformation Token sequence Match detection Transformed token sequence Clones on transformed sequence Formatting Clone pairs 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. } Lexical analysis Transformation Token sequence Match detection Transformed token sequence Clones on transformed sequence Formatting Lexical analysis Transformation Token sequence Match detection Transformed token sequence Clones on transformed sequence Formatting Lexical analysis Transformation Token sequence Match detection Transformed token sequence Clones on transformed sequence Formatting 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. } Next, I explain the clone detection process. In this explanation, I use this source code as an example. And this is the model of the detection process. Lexical analysis is done first of all, and the source code is divided into tokens like this. Next process is transformation. In this process, replacement of identifiers is performed, and this token sequence is generated. Next process is Match detection. CCFinder detects clone pairs from the token sequence which is generated in previous step At last, formatting is performed to make clone pairs map on actual source code. CCFinder outputs the portion information of clone pairs by performing this process.

Aries - その他のメトリクス1(DOC) DOC(S): そのクローンセットに含まれるコード片がどの程度異なるクラスに散らばっているか表す 例: クローンセット S は10個のコード片を含んでいるとする 全てのコード片が異なるクラスにある場合, DOC(S) = ( 10 – 1) / (10 – 1) = 1 5つのクラスにコード片がある場合, DOC(S) = (5 – 1) / (10 – 1) = 0.44 2つのクラスにコード片がある場合, DOC(S) = (2 – 1) / (10 -1) = 0.11 全てのコード片が同一のクラスにある場合, DOC(S) = (1 -1) / (10 -1) = 0 POPの値が大きいクローンセットに対して有効 全てのコード片を1つにまとめるのは難しい

Aries - その他のメトリクス2(SMT) SMT(S): そのクローンセットに含まれる(メソッド単位の)コード片の返り値,引数の型がどの程度一致するかを表す 現在の”一致”の定義 プリミティブ型の場合, まったく同一である時 オブジェクト型の場合, 同一の型もしくは,異なっていても共通の親クラスをもつオブジェクト型の時 例: メソッドAとメソッドBはクローンになっており(クローンセット S) ,それぞれ引数の数は4つである. 全ての引数と返り値の型が一致する場合 SMT(S) = (4 + 1) / (4 + 1) = 1 二つの引数の型が一致する場合 SMT(S) = 2 / (4 + 1) = 0.4 全ての引数と返り値の型が一致しない場合 SMT(S) = 0 / (4 + 1) = 0

Aries - その他のメトリクス3(KMC) KMC(S): そのクローンセットに含まれるコード片が存在するメソッドが,他のメソッドとどの程度結合しているかを表す 結合は以下の三種類で計る メソッド呼び出しの引数 メソッド呼び出しの返り値 メソッド間の共有変数 KMC(S)の値が大きい メソッド間の結合度が大きい リファクタリングすべき?