web-dev-qa-db-ja.com

開発中にコードの重複を検出する方法は?

かなり大きなコードベース、400K LOCのC++があり、コードの重複は問題のようなものです。コードの重複ブロックを効果的に検出できるツールはありますか?

理想的には、これは開発者が開発中にたまに実行して問題の場所を確認するのではなく、使用できるものです。また、このようなツールをCruiseControlに統合して、チェックインのたびにレポートを提供できるといいでしょう。

Duploc を見てみたところ、ニースグラフが表示されましたが、それを使用するにはSmalltalk環境が必要であるため、自動的に実行するのはかなり困難です。

無料のツールはいいかもしれませんが、良い商用ツールがあれば私も興味があります。

75
David Dibben

Simian は、C++プロジェクトの重複コードを検出します。

更新:Java、C#、C、COBOL、Ruby、JSP、ASP、HTML、XML、Visual Basic、Groovyソースコード、さらにはプレーンテキストファイルでも動作します

35
Simon Steele

PMDのCopy-and-Paste-Detector を使用し、次のラッパースクリプトを使用してCruiseControlに統合しました(クラスパスにpmd jarが含まれていることを確認してください)。

チェックは毎晩実行されます。現在の変更セットのファイルのみを一覧表示するように出力を制限する場合は、カスタムプログラミングが必要になる場合があります(アイデア:すべてをチェックし、変更されたファイルの1つが含まれる重複のみを一覧表示します。変更されていないファイルの一部のコード)。 XML出力を使用し、結果を解析することにより実行可能でなければなりません。それが終わったらそのスクリプトを投稿することを忘れないでください;)

手始めに、「テキスト」出力は大丈夫ですが、ユーザーフレンドリーな方法で結果を表示する必要があります。Perlスクリプトを使用して、CPDの「xml」出力からHTMLファイルを生成します。これらは、クルーズのレポートjspが存在するTomcatに投稿することでアクセスできます。開発者はそこからそれらを見ることができ、彼らの汚いハッキングの結果を見ることができます:)

150 KLocコードでは2秒未満で、非常に高速に実行されます(空の行とコメントはその数には含まれません)。

duplicatecheck.xml

<project name="duplicatecheck" default="cpd">

<property name="files.dir" value="dir containing your sources"/>
<property name="output.dir" value="dir containing results for publishing"/>

<target name="cpd">
    <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask"/>
    <cpd minimumTokenCount="100" 
         language="cpp" 
         outputFile="${output.dir}/duplicates.txt"
         ignoreLiterals="false"
         ignoreIdentifiers="false"
         format="text">
        <fileset dir="${files.dir}/">
            <include name="**/*.h"/>
            <include name="**/*.cpp"/>
                <!-- exclude third-party stuff -->
            <exclude name="boost/"/>
            <exclude name="cppunit/"/>
        </fileset>
    </cpd>
</target>
19
user39039

duplo は、Duplocで使用されるアルゴリズムのC実装のようです。コンパイルとインストールは簡単で、オプションには制限がありますが、多かれ少なかれすぐに使用できるようです。

6
benno

PMDプロジェクト を見てください。

私はそれを使用したことはありませんが、常にしたかったです。

4
Andy Lester

これらのDebianパッケージは、これらの行に沿って何かを行うようです:

追伸[ほぼ]重複の検出に関連するすべてのツールには、 debtags タグが必要です。 (しかし、それは何と呼ばれますか?)

3
SamB

まあ、毎晩ソースコードベースでクローン検出器を実行できます。

多くのクローン検出器はソース行を比較することで機能し、正確な重複コードのみを見つけることができます。

上記のCCFinderは、言語トークンを比較することで機能するため、空白の変更の影響を受けません。トークンの変更が1つしかない場合(たとえば、クローンの変数XをYに変更する場合)、元のコードのバリアントであるクローンを検出できます。

理想的なのは上記ですが、バリエーションが比較的arbitrary意的であるクローンを見つける機能です。たとえば、変数を式で置き換えたり、ステートメントをブロックで置き換えたりすることができます。

CloneDRクローン検出器は、Java、C#、C++、COBOL、VB.net、VB6、Fortran、およびその他のさまざまな言語でこれを行います。以下で見ることができます: http://www.semdesigns.com/Products/Clone/index.html

CloneDRエンジンは、複数の言語を処理できるだけでなく、ASCII、ISO-8859-1、UTF8、UTF16、EBCDIC、多数のMicrosoftエンコーディング、および(日本語)Shift- JIS.

このサイトには、C++用のものなど、いくつかのクローン検出実行サンプルレポートがあります。

編集2014年2月:C++ 14のすべてを処理するようになりました。

2
Ira Baxter

ConQAT は、C++コード分析をサポートする優れたツールです。空白を無視して重複を見つけることができます。非常に便利なGUIとコンソールインターフェースを備えています。柔軟性があるため、セットアップは簡単ではありません。 このブログ投稿はC++プロジェクトのセットアップに非常に便利です が見つかりました。

1
user2648800

CCFinderX は、複数のプログラミング言語(Java、C、C++、COBOL、VB、C#)をサポートする無料の(社内使用)クローンコード検出器です。

1
bk1e

同じ( http://sourceforge.net/projects/same/ )は非常に単純ですが、トークンではなくテキスト行で動作します。これは、洗練されたクローンファインダの1つによってサポートされています。

1
Sean McMillan

「同一の」コードスニペットを見つけるのは比較的簡単です。すでにこれを行う既存のツールがあります(他の回答を参照)。

時にはそれは良いことですが、時にはそうではありません。あまりにも細かい「レベル」で行うと、開発時間を遅らせる可能性があります。つまり、非常に多くのコードをリファクタリングしようとすると、目標が失われます(そして、おそらくマイルストーンとスケジュールが破綻します)。

より難しいのは、適切な文書化なしに、同じ(ただし類似の)入力やアルゴリズムを使用する複数の関数/メソッドを見つけることです。

同じことを行うために2つ以上の方法が必要であり、プログラマーが1つのインスタンスを修正しようとするが、他のインスタンスを修正することを忘れる(または存在することを知らない)場合、ソフトウェアのリスクが高まります。

1
Max

SourceMeter ツールを使用して、コードの重複を検出できます。これはコマンドラインツール(コンパイラに非常に類似)であるため、 CruiseControl your前述、または Jenkins などの継続的統合ツールに簡単に統合できます。

1
Rudolf FERENC

Java、C#、C++、C、Objective-C、JavaScriptをサポートする Simian もあります...

Hudson(CPDなど)でサポートされています。

あなたがオープンソースプロジェクトでない限り、Simianに対してpayをする必要があります。

0
Wernight