以下、本実施の形態を図面を参照して説明する。
[第1の実施の形態]
図1は、第1の実施の形態の情報処理装置を示す図である。情報処理装置1は、ユーザによるソフトウェアの開発作業を支援する装置である。ソフトウェア開発の現場では、第1のプログラムに含まれる機能を、第2のプログラムでも実現するために、第1のプログラムに含まれる当該機能のコード部分(コード片)を複製して、第2のプログラムに埋め込むことがある。埋め込み時には、該当のコード部分に含まれる変数名や処理名(例えば、関数名、オブジェクト名、および、サブルーチン名など)は、埋め込み先である第2のプログラムに合わせて変更される。
このような作業が行われることで、複数のソースプログラム内には、共通の機能を実現する類似するコード(処理の記述内容は共通しているが、利用される変数名や処理名などが互いに異なるコード)が含まれ得る。情報処理装置1は、このように複数のソースプログラム内で互いに類似するコード(類似コードあるいはコードクローンと称することがある)を検出し、共通化する機能を提供する。
具体的には、情報処理装置1は、類似コードにおける共通部分と、変数名や処理名などの相違部分とを分けて管理し、相違部分に対してユーザによる事後的な設定を許容する。すると、各ソースプログラム内の該当コードの記述を、共通コードの呼び出し、および、該当のソースプログラムに応じた変数名や処理名の設定の記述に置換できる。情報処理装置1は、こうしてソースプログラム内の類似コードを共通化することで、コードの保守性および再利用可能性を高める。特に、情報処理装置1は、類似コードにおける相違部分の抽出方法を工夫することで、ソフトウェアの開発作業の効率を改善する。具体的には、次の通りである。
情報処理装置1は、記憶部1aおよび演算部1bを有する。記憶部1aは、RAM(Random Access Memory)などの揮発性記憶装置でもよいし、HDD(Hard Disk Drive)やフラッシュメモリなどの不揮発性記憶装置でもよい。演算部1bは、CPU(Central Processing Unit)、DSP(Digital Signal Processor)、ASIC(Application Specific Integrated Circuit)、FPGA(Field Programmable Gate Array)などを含み得る。演算部1bはプログラムを実行するプロセッサであってもよい。ここでいう「プロセッサ」には、複数のプロセッサの集合(マルチプロセッサ)も含まれ得る。すなわち、情報処理装置1は、記憶部1a(メモリ)と演算部1b(プロセッサ)とを含む。情報処理装置1は、コンピュータと呼ばれてもよい。
記憶部1aは、複数のソースコードを記憶する。複数のソースコードは、ソースコードPF1,PF2を含む。記憶部1aは、演算部1bによる処理に応じて生成される、類似コードSC1,SC2、相違単語情報D1、相違文字情報D2およびパラメータ化情報D3を記憶する。ここで、図1において、各コードの左側に付された数値は行番号である。
ソースコードPF1,PF2は、ユーザによって作成されたプログラムのコードである。ソースコードPF1,PF2は、所定の命令や変数名および処理名などを示す文字列を含む。命令を示す文字または文字列(例えば、“PERFORM”、“IF”、“=”(イコール記号)、“THEN”、“END−IF”、“MOVE”など)は、プログラム言語に応じて予め定められた予約語である。プログラム言語に応じた予約語の情報は、記憶部1aに予め格納されている。
類似コードSC1,SC2は、ソースコードPF1,PF2それぞれから検出された類似コードである。相違単語情報D1は、類似コードSC1,SC2から抽出された互いに相違する単語(相違単語と称する)の情報である。相違文字情報D2は、相違単語間における相違する文字(相違文字と称する)の位置の情報である。パラメータ化情報D3は、各類似コードに含まれるパラメータ化対象の文字列(置換文字列と称する)を示す情報である。置換文字列は、各類似コード内でパラメータ化可能な(ユーザによる設定を許容する)文字列を表している。パラメータ化情報D3は、各類似コードを共通コード化した場合の共通コードに含まれるパラメータ数の情報も含む。パラメータ数は、類似コードSC1(または、類似コードSC2)においてパラメータ化の対象の文字列部分の数ともいえる。
情報処理装置1が実行する類似コードの共通化の処理において、ソースコードPF1,PF2が入力であり、パラメータ化情報D3が出力である。ソフトウェア開発を行うユーザは、例えば、パラメータ化情報D3の内容を参照することで、複数のソースコード内における置換文字列およびパラメータ数を確認することができる。
演算部1bは、ソースコードPF1,PF2の入力を受け付ける(ただし、入力されるソースコードの数は3以上でもよい)。演算部1bは、ソースコードPF1,PF2を比較して、類似コードSC1,SC2を検出する(類似コード検出)。例えば、ソースコードPF1,PF2では、両者とも、2行目から6行目の記述において処理内容を示す予約語の記述が一致し、変数名を表す文字列が相違している。一方、ソースコードPF1,PF2では、1行目および7行目の記述について、処理内容を示す予約の記述が相違している(処理名を表す文字列も相違している)。このため、演算部1bは、ソースコードPF1,PF2それぞれの2行目から6行目の記述を類似コードとして検出する。すなわち、演算部1bは、ソースコードPF1の2行目から6行目の記述に相当する類似コードSC1を検出する。演算部1bは、ソースコードPF2の2行目から6行目の記述に相当する類似コードSC2を検出する。
次に、演算部1bは、互いに類似する類似コードSC1,SC2それぞれにおいて共通の箇所に記述され互いに相違する複数の単語(相違単語)を抽出し、当該相違単語の抽出結果を示す相違単語情報D1を生成する。例えば、類似コードSC1の1行目には、“IF カウントフラグ = “1” THEN”という記述がある。また、類似コードSC2の1行目には、“IF ラウンドフラグ = “1” THEN”という記述がある。
この場合、共通の処理内容における“IF”と“=”との間の共通の箇所に、類似コードSC1では“カウントフラグ”という単語を表す文字列が記述され、類似コードSC2では“ラウンドフラグ”という単語を表す文字列が記述されている。したがって、類似コードSC1の単語“カウントフラグ”および類似コードSC2の単語“ラウンドフラグ”は、類似コードSC1,SC2それぞれにおいて、共通の箇所に記述され互いに相違する複数の単語である。
同様に、類似コードSC1の単語“カウント出力”および類似コードSC2の単語“ラウンド出力”も、類似コードSC1,SC2それぞれにおいて、共通の箇所に記述され互いに相違する複数の単語である。このため、演算部1bは、“カウントフラグ”と“ラウンドフラグ”との単語ペアp1、および、“カウント出力”と“ラウンド出力”との単語ペアp2を、類似コードSC1,SC2から抽出し、相違単語情報D1を生成する。
次に、演算部1bは、各単語ペア(単語ペアに属する複数の単語の間)で相違する文字(相違文字)の位置(相違位置)を検出し、相違位置の検出結果を示す相違文字情報D2を生成する。ここで、演算部1bは、各単語の先頭から後方に向かって、文字の位置を表す番号を“1”、“2”、“3”、・・・と昇順に付与する。
単語ペアp1の場合、単語“カウントフラグ”と単語“ラウンドフラグ”とを比較すると、各単語の先頭(位置番号“1”)が“カ”および“ラ”で異なっている。また、各単語の先頭から4番目(位置番号“4”)が“ト”および“ド”で異なっている。このため、演算部1bは、単語ペアp1に対して、相違位置“1−1,4−4”を検出する。ここで、相違位置の表記において、“1−1”(2つの単語の文字位置をハイフン記号で結んだ表現)は、両単語の1番目の文字列同士が相違していることを示す。同様に“4−4”は、両単語の4番目の文字列同士が相違していることを示す。単語ペアp2の場合も、単語ペアp1と同様である。したがって、演算部1bは、単語ペアp1に対して相違位置“1−1,4−4”を、単語ペアp2に対して相違位置“1−1,4−4”を検出し、相違文字情報D2を生成する。
次に、演算部1bは、各相違単語について、相違位置の前方に連なる1以上の文字および相違位置の後方に連なる1以上の文字の両方または何れか一方と相違文字とを含む文字列を、パラメータ化の対象部分とする置換文字列と決定する。
例えば、演算部1bは、単語ペアp1では、相違文字“カ”および“ラ”について、各相違文字の相違位置“1”の後方に連なる1以上の文字を(各文字の並び順を維持して)各相違文字に結合し、置換文字列とする。一例として、演算部1bは、単語ペアp1について、類似コードSC1では“カウントフラグ”を、類似コードSC2では“ラウンドフラグ”をそれぞれ置換文字列とすることが考えられる。この場合、演算部1bは、単語ペアp2について、類似コードSC1では“カウント出力”を、類似コードSC2では“ラウンド出力”をそれぞれ置換文字列とする。すると、パラメータ数は2である。
あるいは、演算部1bは、類似コードSC1,SC2と置換文字列の候補とを用いて作成される共通コードに含まれるパラメータの数に基づいて、置換文字列を決定してもよい。例えば、単語ペアp1,p2の関係では、類似コードSC1では“カウント”を、類似コードSC2では“ラウンド”を、それぞれ置換文字列とした方がパラメータの数を1に抑えられる。そこで、演算部1bは、各相違単語のうち相違位置から1文字ずつ前方または後方に文字列範囲を拡大しながらパラメータの数の増減を確認し、類似コードSC1,SC2を共通化するときのパラメータの数がより少なくなる置換文字列を特定してもよい。上記の例でいえば、演算部1bは、各相違単語の先頭の“カ”および“ラ”から後方に1文字ずつ拡大しながらパラメータの数の増減を確認し、類似コードSC1,SC2を共通化するときのパラメータの数がより少なくなる置換文字列を特定してもよい。パラメータの数が少ない方が、共通コードの可読性や再利用可能性を高められるからである。
また、演算部1bは、相違位置から前方または後方に1文字ずつ検査して、相違単語に含まれる所定の記号(例えば、ハイフン“−”やスラッシュ“/”などの区切り文字)を検出することで、置換文字列とする文字列範囲を決定してもよい。特定の記号によって、変数名や処理名などの意味的な区切りを表すことが多いからである。あるいは、演算部1bは、文字の種類が変わる境界(例えば、アルファベット/数字の境界、アルファベットの大文字/小文字の境界、アルファベット/かな文字の境界など)を検出することで、置換文字列とする文字列範囲を決定してもよい。区切り文字などと同様に、文字の種類が変わる位置に、変数名や処理名などの意味的な区切りが存在する可能性が高いからである。
そして、演算部1bはパラメータ化情報D3を出力する。例えば、演算部1bは、上記のように類似コードSC1,SC2におけるパラメータ数がより少なくなるように、パラメータ化を行う。上記の例の場合、演算部1bは、類似コードSC1について相違文字“カ”に対し、後方の文字列“ウント”を結合した“カウント”、および、類似コードSC2について相違文字“ラ”に対し、後方の文字列“ウンド”を結合した“ラウンド”を置換文字列とする。なぜなら、次の1文字後方まで置換文字列を拡張すると、“カウントフ”と“ラウンドフ”とに対して1つ目のパラメータを、“カウント出”と“ラウンド出”とに対して2つ目のパラメータを、それぞれ用意することになり、パラメータ数が1から2へ増加するからである。この場合、パラメータ化情報D3は、類似コードSC1における置換文字列“カウント”、類似コードSC2における置換文字列“ラウンド”の情報、および、パラメータ数“1”の情報を含む。
例えば、ユーザは、パラメータ化情報D3の内容を参照して、ソースコードPF1,PF2それぞれの置換文字列およびパラメータを1つ設けることで、ソースコードPF1,PF2の一部を共通化できることを確認することができる。ユーザは、当該確認に応じて、複数のソースコード間におけるコード片の複製状況や共通化を行うか否かの決定などを行える。演算部1bは、共通化の指示を受けて、パラメータ化情報D3を基に、ソースコードPF1,PF2の類似コード部分を共通化した共通コードを生成し、ソースコードPF1,PF2の類似コード部分を共通コードで置換する処理を行ってもよい。
ここで、例えば、互いに類似するコード部分について、単に相違する文字の箇所のみを差分として検出し、当該コード部分を共通化することも考えられる。この場合、上記の例では、“カウントフラグ”の“カ”および“ラウンドフラグ”の“ラ”が1つ目の差分、“カウントフラグ”の“ト”および“ラウンドフラグ”の“ド”が2つ目の差分として検出されることになる。この場合、各相違単語の1番目および4番目の文字をプレースホルダに置き換えてパラメータ化する。例えば、1番目のプレースホルダを“!”(エクスクラメーションマーク)とし、4番目のプレースホルダを“?”(クエスチョンマーク)とする。すると、共通コード内で相違単語に相当する単語を“!ウン?フラグ”と表すことになる。
しかし、このように、互いに類似するコード部分を単純に文字列として比較し、相違箇所のみをパラメータ化するだけでは、ソフトウェア開発の効率性の観点からは不十分である。なぜなら、共通化したコード内に相違箇所のみがパラメータとして点在すると、個々のパラメータのコード内での意味が薄れ、また、パラメータの数が増え、可読性や再利用可能性が低い状態でパラメータ化する部分が導出されるおそれがあるからである。
より具体的には、共通化したコード内に相違箇所(上記“!”や“?”の箇所)のみがパラメータとして点在すると、個々のパラメータのコード内での意味が明確でなくなる。例えば、上記のように“!ウン?フラグ”では、当該変数名が何を表しているかが分かり難く、可読性が低下する。また、上記のように相違箇所(上記“!”や“?”の部分)毎にパラメータ化されてしまうので、パラメータの数が増え、また、置換対象部分にあてはめる文字列の自由度が減り、再利用可能性が低下する。例えば、上記のように共通コード内で、“!ウン?フラグ”のように変数名を表すとすると、該当部分の記述が“エンドフラグ”であるコード片には当該共通コードを再利用できない。
そこで、情報処理装置1は、各類似コードにおける相違単語のうち、互いに相違する文字位置から前方および後方の両方または何れか一方に1文字以上拡大した文字列範囲を、パラメータ化対象の置換文字列とする。これにより、単に相違箇所のみをパラメータ化するよりも、共通コードの可読性、および、再利用可能性を高めることができる。
例えば、上記のように、情報処理装置1は、パラメータ化候補の文字列範囲を1文字ずつ拡大しながらパラメータ数の増減を確認し、共通コードにおけるパラメータ数が少なくなる置換文字列を特定する。すると、プレースホルダを“?”として、“カウントフラグ”や“ラウンドフラグ”を、“?フラグ”のように表すことができ、何らかのフラグを表していることが明確となり、置換文字列の可読性を高められる。また、パラメータ数を少なくすることで、ある程度まとまった文字列範囲をパラメータ化できる。このため、例えば、上記のように該当箇所に“エンドフラグ”を含むコード片にも、“?フラグ”で共通化した共通コードを適用することが可能となり、共通コードの再利用可能性を高められる。
このように、情報処理装置1は、意味のある文字列範囲をパラメータ化対象とすることで、共通コードの可読性、および、再利用可能性を高め、ユーザによるプログラムの作成や保守に伴う作業を省力化できる。その結果、情報処理装置1は、ソフトウェア開発の効率を改善できる。
次に、ユーザによるソフトウェア開発を支援するサーバコンピュータ(単にサーバと称することがある)を例示して、上記の情報処理装置1の機能をより具体的に説明する。
[第2の実施の形態]
図2は、第2の実施の形態のサーバのハードウェア例を示す図である。サーバ100は、情報処理装置1の一例である。サーバ100は、プロセッサ101、RAM102、HDD103、画像信号処理部104、入力信号処理部105、媒体リーダ106および通信インタフェース107を有する。各ユニットはサーバ100のバスに接続されている。
プロセッサ101は、サーバ100の情報処理を制御する。プロセッサ101は、マルチプロセッサであってもよい。プロセッサ101は、例えばCPU、DSP、ASICまたはFPGAなどである。プロセッサ101は、CPU、DSP、ASIC、FPGAなどのうちの2以上の要素の組み合わせであってもよい。
RAM102は、サーバ100の主記憶装置である。RAM102は、プロセッサ101に実行させるOS(Operating System)のプログラムやアプリケーションプログラムの少なくとも一部を一時的に記憶する。また、RAM102は、プロセッサ101による処理に用いる各種データを記憶する。
HDD103は、サーバ100の補助記憶装置である。HDD103は、内蔵した磁気ディスクに対して、磁気的にデータの書き込みおよび読み出しを行う。HDD103は、OSのプログラム、アプリケーションプログラム、および各種データを記憶する。サーバ100は、フラッシュメモリやSSD(Solid State Drive)などの他の種類の補助記憶装置を備えてもよく、複数の補助記憶装置を備えてもよい。
画像信号処理部104は、プロセッサ101からの命令に従って、サーバ100に接続されたディスプレイ11に画像を出力する。ディスプレイ11としては、CRT(Cathode Ray Tube)ディスプレイや液晶ディスプレイなどを用いることができる。
入力信号処理部105は、サーバ100に接続された入力デバイス12から入力信号を取得し、プロセッサ101に出力する。入力デバイス12としては、例えば、マウスやタッチパネルなどのポインティングデバイス、キーボードなどを用いることができる。
媒体リーダ106は、記録媒体13に記録されたプログラムやデータを読み取る装置である。記録媒体13として、例えば、フレキシブルディスク(FD:Flexible Disk)やHDDなどの磁気ディスク、CD(Compact Disc)やDVD(Digital Versatile Disc)などの光ディスク、光磁気ディスク(MO:Magneto-Optical disk)を使用できる。また、記録媒体13として、例えば、フラッシュメモリカードなどの不揮発性の半導体メモリを使用することもできる。媒体リーダ106は、例えば、プロセッサ101からの命令に従って、記録媒体13から読み取ったプログラムやデータをRAM102またはHDD103に格納する。
通信インタフェース107は、ネットワーク10を介して他の装置と通信を行う。通信インタフェース107は、有線通信インタフェースでもよいし、無線通信インタフェースでもよい。
ここで、サーバ100は、複数のソースプログラムに含まれるコードクローンの共通化を支援する機能を提供する。まず、具体的なソースコードの例を挙げ、コードクローンの抽出方法を例示する。
図3は、コードクローンの抽出例を示す図である。ソースコードP1,P2は、ユーザにより作成されたプログラムである。第2の実施の形態では、プログラム言語の一例として、COBOLを想定する。ただし、プログラム言語は、Fortran、C、Java(登録商標)など、種々のものを利用できる。ソースコードP1のファイル名は、“PROG001.CBL”である。ソースコードP2のファイル名は、“PROG002.CBL”である。なお、以下に示す図中、各コードの左側に付された数値は行番号である。
例えば、サーバ100は、ソースコードP1,P2に含まれる予約語と予約語以外の単語とを区別し、予約語以外の単語を匿名化する。サーバ100は、予約語以外の単語のうち、引用符(ダブルクォーテーションなど)で囲われた単語を“$文字列$”と匿名化し、引用符なしで記述された単語を“$名前$”と匿名化する。
コードP1aは、ソースコードP1の匿名化処理後のコードである。コードP1aでは、例えば、“PERFORM”や“IF”などの予約語以外の“処理開始”、“S11Aフラグ”、“S11A名前”、“エラー処理”および“処理終了”といった文字列が“$名前$”と匿名化されている。
コードP2aは、ソースコードP2の匿名化処理後のコードである。コードP2aでは、コードP1aと同様に、予約語以外の““開始””および““終了””といった引用符で囲われた文字列が“$文字列$”と匿名化されている。また、予約語以外の“S12Aフラグ”、“S12A名前”および“エラー処理”といった文字列が“$名前$”と匿名化されている。
コードP1a,P2aのうち、2行目から6行目の範囲(コード片fr1)では、予約語および匿名化部分の記述内容が一致している。このため、サーバ100は、ソースコードP1,P2のうち、コード片fr1に対応する部分を、互いに類似するコード部分(コードクローンに相当する部分)として特定する。
次に、コードクローンを共通化するために考えられる単純な方法を例示し、その問題点を説明する。
図4は、コードクローン共通化の単純な方法の例(その1)を示す図である。例えば、コードC11は、ソースコードP1のうちのコード片fr1に対応するコードクローンである。同様に、コードC12は、ソースコードP2のうちのコード片fr1に対応するコードクローンである。これらをコンピュータにより比較させ、コードC11,C12の間で相違単語のペアを取得させ、テーブルT1に記録させる。この場合、コードC11の単語“S11Aフラグ”およびコードC12の単語“S12Aフラグ”が相違単語の1つ目のペアである。また、コードC11の単語“S11A名前”およびコードC12の単語“S12A名前”が相違単語の2つ目のペアである。1つ目のペアおよび2つ目のペアの両方とも、相違文字は先頭から3番目の文字である。テーブルT1における相違の項目には、両コードの相違文字が登録されている。例えば、相違の項目における“1<=>2”の表記は、コードC11側の文字“1”と、コードC12側の文字“2”とが相違することを表している(以下の説明でも、同様の表現を用いることがある)。
単純に相違文字の部分だけをパラメータ化すると、例えば、プレースホルダを“?”として、コード片fr1の“$名前$”部分を“S1?Aフラグ”や“S1?A名前”のように記述することになる。共通コードCn1は、当該記述を用いたコードクローンの共通化結果である。ここで、共通コードCn1のファイル名を“COMMON01.CBL”とする。
すると、ソースコードP1の該当のコードクローンを、共通コードCn1の呼び出し(コピー)、および、パラメータに相当するプレースホルダへの“1”の設定、を行う記述に置換できる。より具体的には、ソースコードP1のコードC11に相当する部分を、“COPY COMMON01 REPLACING ==?== BY ==1==”という記述に置換できる。ソースコードPr1は、ソースコードP1に対する当該置換後の記述を示す。
同様に、ソースコードP2の該当のコードクローンを、共通コードCn1の呼び出し(コピー)、および、パラメータに相当するプレースホルダへの“2”の設定、を行う記述に置換できる。より具体的には、ソースコードP2のコードC12に相当する部分を、“COPY COMMON01 REPLACING ==?== BY ==2==”という記述に置換できる。ソースコードPr2は、ソースコードP2に対する当該置換後の記述を示す。
しかし、上記のように、“$名前$”部分を、“S1?Aフラグ”や“S1?A名前”のように相違箇所のみをパラメータ化してしまうと、共通コードCn1の再利用可能性が低下する。例えば、「S21Bフラグ」の追加時に、共通コードCn1を再利用できないことになる。
図5は、コードクローン共通化の単純な方法の例(その2)を示す図である。次の例として、ソースコードP1,P2とは別の2つのソースコードを考える。当該2つのソースコードに対するコードクローンとして、コードC21,C22が検出されたとする。この場合、コードC21の単語“カウントフラグ”およびコードC22の単語“ラウンドフラグ”が相違単語の1つ目のペアである。また、コードC21の単語“カウント出力”およびコードC22の単語“ラウンド出力”が相違単語の2つ目のペアである。1つ目のペアおよび2つ目のペアの両方とも、相違文字は、先頭から1番目の文字、および、先頭から4番目の文字である。テーブルT2は、コードC21,C22における相違文字を示している。
単純に相違文字の部分だけをパラメータ化することを考える。例えば、1つ目のプレースホルダを“X”、2つ目のプレースホルダを“Y”とする。この場合、“カウントフラグ”および“ラウンドフラグ”は、“XウンYフラグ”と表される。また、“カウント出力”および“ラウンド出力”は、“XウンY出力”と表される。共通コードCn2は、当該記述を用いたコードクローンの共通化結果である。ここで、共通コードCn2のファイル名を“COMMON02.CBL”とする。
すると、元の第1のソースコードのコードC21に相当する部分を、共通コードCn2の呼び出し(コピー)、プレースホルダ“X”への文字“カ”の設定、および、プレースホルダ“Y”への文字“ト”の設定、を行う記述に置換できる。より具体的には、ソースコードPr3は、当該置換後のコードである。ソースコードPr3における“COPY COMMON02 REPLACING ==X== BY ==カ== ==Y== BY ==ト==”の記述が置換後の記述である。
同様に、元の第2のソースコードのコードC22に相当する部分を共通コードCn2の呼び出し(コピー)、プレースホルダ“X”への文字“ラ”の設定、および、プレースホルダ“Y”への文字“ド”の設定、を行う記述に置換できる。より具体的には、ソースコードPr4は、当該置換後のコードである。ソースコードPr4における“COPY COMMON02 REPLACING ==X== BY ==ラ== ==Y== BY ==ド==”の記述が置換後の記述である。
しかし、上記のように、“XウンYフラグ”や“XウンY出力”のように相違箇所のみをパラメータ化してしまうと、共通コードCn2の可読性が低下する。例えば、“XウンYフラグ”によって置換される文字の意味が分かりにくい。
このように、可読性および再利用可能性の低い共通コードが作成されてしまうと、ソフトウェアの円滑な開発の妨げとなり、開発作業の効率を低下させる要因になり得る。そこで、サーバ100は、パラメータ化の方法を工夫し、ソフトウェアの円滑な開発を支援する機能を提供する。
図6は、サーバの機能例を示す図である。サーバ100は、記憶部110、コードクローン検出部120、相違単語抽出部130、相違文字抽出部140および置換文字列決定部150を有する。
記憶部110は、RAM102やHDD103に確保された記憶領域を用いて実現できる。コードクローン検出部120、相違単語抽出部130、相違文字抽出部140および置換文字列決定部150は、RAM102に記憶されたプログラムを、プロセッサ101が実行することで実現される。コードクローン検出部120、相違単語抽出部130、相違文字抽出部140および置換文字列決定部150それぞれをプログラムのモジュールと考えてもよい。
記憶部110は、ソースコード群111、コードクローン情報112、相違単語情報113、相違文字情報114、補助情報115およびパラメータ化情報116を記憶する。
ソースコード群111は、ユーザによって作成されたソースプログラムの集合である。第2の実施の形態の例では、各ソースコードは、前述のようにCOBOLを用いて記述されている。
コードクローン情報112は、コードクローン検出部120によりソースコード群111から検出されたコードクローンの情報である。
相違単語情報113は、相違単語抽出部130によりコードクローン情報112から抽出された相違単語の情報である。
相違文字情報114は、相違文字抽出部140により相違単語情報113から抽出された相違文字の位置の情報である。
補助情報115は、置換文字列決定部150による置換文字列決定に用いられる補助的な情報(置換文字列を決定するための条件の情報)である。ただし、補助情報115を用いなくてもよい。ここで、前半の説明(図26までの説明)では補助情報115を用いない例を説明し、その後、図27から図34までの説明において、補助情報115を用いる例を説明する。
パラメータ化情報116は、置換文字列決定部150により出力されるパラメータ化の結果である。なお、記憶部110は、プログラム言語に応じた予約語の情報も予め記憶する。
コードクローン検出部120は、ソースコード群111に含まれる複数のソースコードを比較して、コードクローン(互いに類似するコード片)を検出する。例えば、ユーザは、コードクローン検出部120に、比較対象とする2以上のソースコードのファイル名を指定することができる。例えば、コードクローン検出部120は、図3で例示したように、指定された各ソースコードに対して匿名化の処理を行う。コードクローン検出部120は、匿名化後の各コードを比較することで、コードクローンを検出する。コードクローン検出部120は、コードクローンの検出結果であるコードクローン情報112を生成し、記憶部110に格納する。
相違単語抽出部130は、記憶部110に記憶されたコードクローン情報112に基づいて、各コードクローンから共通の箇所に記述され互いに相違する相違単語を抽出する。相違単語抽出部130は、相違単語の抽出結果である相違単語情報113を生成し、記憶部110に格納する。
相違文字抽出部140は、記憶部110に記憶された相違単語情報113に基づいて、各相違単語における相違文字の位置(相違位置)を抽出する。相違文字抽出部140は、相違位置の抽出結果である相違文字情報114を生成し、記憶部110に格納する。
置換文字列決定部150は、記憶部110に記憶された相違文字情報114に基づいて、各コードクローンでパラメータ化の対象とする置換文字列を決定する。具体的には、置換文字列決定部150は、各相違単語において、相違文字情報114で示される相違位置から前方および後方に1文字ずつ置換文字列の候補とする文字列範囲を広げていく。置換文字列決定部150は、当該文字列範囲を1文字広げるたびに、現在の文字列範囲で示される置換文字列の候補が置換文字列の決定条件に合致するか否かを判定し、置換文字列を決定する。ここで、置換文字列の決定条件とは、「コードクローンを共通化した際の共通コードにおけるパラメータ数が少なくなる置換文字列を優先する」というものである。置換文字列決定部150は、各コードクローン(あるいは各ソースコード)に対応する置換文字列およびコードクローン部分を共通化した際のパラメータ数の情報を含むパラメータ化情報116を生成し、記憶部110に格納する。
図7は、ソースコードの例を示す図である。ソースコード群111は、ソースコードP1,P2,P3,P4を含む。ソースコードP1,P2は、図2で例示した各ソースコードと同一である。また、ソースコードP3のファイル名は“PROG003.CBL”である。ソースコードP4のファイル名は“PROG004.CBL”である。
図8は、コードクローン情報の例を示す図である。例えば、コードクローン検出部120は、ユーザによりソースコードP1,P2のファイル名の入力を受け付けると、記憶部110に記憶されたソースコードP1,P2を比較して、コードクローン情報CL1を生成する。ここで、“コードクローン情報CL1”の表記のうち、“CL1”の部分をコードクローン情報の識別名(識別情報)とする。コードクローン情報CL1は、コードC11,C12を含む。
コードC11は、ソースコードP1の一部分(コード片)である。コードC11は、コードC12に類似するコードであり、ソースコードP1,P2の比較に応じて検出されたコードクローンである。コードC12は、ソースコードP2の一部分である。コードC12は、コードC11に類似するコードであり、ソースコードP1,P2の比較に応じて検出されたコードクローンである。
また、例えば、コードクローン検出部120は、ユーザによりソースコードP3,P4のファイル名の入力を受け付けると、記憶部110に記憶されたソースコードP3,P4を比較して、コードクローン情報CL2を生成する。
コードクローン情報CL2は、コードC21,C22を含む。コードC21は、ソースコードP3の一部分である。コードC21は、コードC22に類似するコードであり、ソースコードP3,P4の比較に応じて検出されたコードクローンである。コードC22は、ソースコードP4の一部分である。コードC22は、コードC21に類似するコードであり、ソースコードP3,P4の比較に応じて検出されたコードクローンである。
図9は、相違単語情報の例を示す図である。相違単語情報113は、コードクローン、ペア識別子、第1コードおよび第2コードの項目を含む。
コードクローンの項目には、コードクローン情報の識別名が登録される。ペア識別子の項目には、単語ペア(3以上のコードクローンに対しては3以上の相違単語の組み合わせとなるため、単語セットとなる)の識別子が登録される。第1コードの項目には、1つ目のコードクローンにおける相違単語が登録される。第2コードの項目には、2つ目のコードクローンにおける相違単語が登録される。相違単語情報113には、1つのコードクローン情報の識別名に対し、異なるペア識別子が設定された複数のレコードが登録され得る。
また、図8の例では、コードクローン情報CL1に対して第1コードは、コードC11である。コードクローン情報CL1に対して第2コードは、コードC12である。同様に、コードクローン情報CL2に対して第1コードは、コードC21である。コードクローン情報CL2に対して第2コードは、コードC22である。
例えば、相違単語情報113には、コードクローンが“CL1”、ペア識別子が“単語ペアa1”、第1コードが“S11Aフラグ”、第2コードが“S12Aフラグ”という情報が登録される。これは、コードクローン情報CL1において、コードC11における単語“S11Aフラグ”、および、コードC12における単語“S12Aフラグ”それぞれが相違単語として抽出されたことを示す。また、当該相違単語のペアのペア識別子が“単語ペアa1”であることを示す。
また、相違単語情報113には、コードクローンが“CL1”、ペア識別子が“単語ペアa2”、第1コードが“S11A名前”、第2コードが“S12A名前”という情報が登録される。これは、コードクローン情報CL1において、コードC11における単語“S11A名前”、および、コードC12における単語“S12A名前”それぞれが相違単語として抽出されたことを示す。また、当該相違単語のペアのペア識別子が“単語ペアa2”であることを示す。
また、相違単語情報113には、コードクローンが“CL2”、ペア識別子が“単語ペアb1”、第1コードが“カウントフラグ”、第2コードが“ラウンドフラグ”という情報が登録される。これは、コードクローン情報CL2において、コードC21における単語“カウントフラグ”、および、コードC22における単語“ラウンドフラグ”それぞれが相違単語として抽出されたことを示す。また、当該相違単語のペアのペア識別子が“単語ペアb1”であることを示す。
更に、相違単語情報113には、コードクローンが“CL2”、ペア識別子が“単語ペアb2”、第1コードが“カウント出力”、第2コードが“ラウンド出力”という情報が登録される。これは、コードクローン情報CL2において、コードC21における単語“カウント出力”、および、コードC22における単語“ラウンド出力”それぞれが相違単語として抽出されたことを示す。また、当該相違単語のペアのペア識別子が“単語ペアb2”であることを示す。
図10は、相違文字情報の例を示す図である。相違文字情報114は、コードクローン、ペア識別子、第1コード、第2コードおよび相違位置の項目を含む。ここで、コードクローン、ペア識別子、第1コードおよび第2コードに登録される情報の内容は、図9で例示した相違単語情報113の同名の項目に登録される情報の内容と同じである。相違文字情報114は、相違位置の項目を更に含む点が、相違単語情報113と異なる。
相違位置の項目には、単語ペアに属する各相違単語における文字の相違位置が登録される。ここで、相違文字抽出部140および置換文字列決定部150は、単語内の各文字の位置を位置番号によって管理する。具体的には、単語の先頭の文字から後方の文字へ向かうに従って1文字ずつ、“1”、“2”、“3”、・・・と昇順の位置番号が付与される。そして、相違文字抽出部140は、“3−3”のように位置番号をハイフン記号(“−”)で結合した相違位置の情報を相違文字情報114に登録する。相違位置の表記のうち、ハイフン記号の左側の位置番号は第1コードに含まれる相違単語の相違位置に相当する。同様に、ハイフン記号の右側の位置番号は第2コードに含まれる相違単語の相違位置に相当する。
例えば、相違文字情報114には、コードクローンが“CL1”、ペア識別子が“単語ペアa1”、第1コードが“S11Aフラグ”、第2コードが“S12Aフラグ”、相違位置が“3−3”という情報が登録される。これは、コードクローン情報CL1におけるコードC11の相違単語“S11Aフラグ”、および、コードC12の相違単語“S12Aフラグ”において、それぞれ先頭から3番目の文字が互いに相違していることを示す。ここで、“S11Aフラグ”の先頭から3番目の文字は“1”である。“S12Aフラグ”の先頭から3番目の文字は“2”である。
また、相違文字情報114には、コードクローンが“CL1”、ペア識別子が“単語ペアa2”、第1コードが“S11A名前”、第2コードが“S12A名前”、相違位置が“3−3”という情報が登録される。これは、コードクローン情報CL1におけるコードC11の相違単語“S11A名前”、および、コードC12の相違単語“S12A名前”において、それぞれ先頭から3番目の文字が互いに相違していることを示す。ここで、“S11A名前”の先頭から3番目の文字は“1”である。“S12A名前”の先頭から3番目の文字は“2”である。
また、相違文字情報114には、コードクローンが“CL2”、ペア識別子が“単語ペアb1”、第1コードが“カウントフラグ”、第2コードが“ラウンドフラグ”、相違位置が“1−1,4−4”という情報が登録される。これは、コードクローン情報CL2におけるコードC21の相違単語“カウントフラグ”、および、コードC22の相違単語“ラウンドフラグ”において、それぞれ先頭から1番目の文字が互いに相違していることを示す。同様に、先頭から4番目の文字が互いに相違していることを示す。ここで、“カウントフラグ”の先頭から1番目の文字は“カ”である。“ラウンドフラグ”の先頭から1番目の文字は“ラである。“カウントフラグ”の先頭から4番目の文字は“ト”である。“ラウンドフラグ”の先頭から4番目の文字は“ド”である。
更に、相違文字情報114には、コードクローンが“CL2”、ペア識別子が“単語ペアb2”、第1コードが“カウント出力”、第2コードが“ラウンド出力”、相違位置が“1−1,4−4”という情報が登録される。これは、コードクローン情報CL2におけるコードC21の相違単語“カウント出力”、および、コードC22の相違単語“ラウンド出力”において、それぞれ先頭から1番目の文字が互いに相違していることを示す。同様に、先頭から4番目の文字が互いに相違していることを示す。ここで、“カウント出力”の先頭から1番目の文字は“カ”である。“ラウンド出力”の先頭から1番目の文字は“ラ”である。“カウント出力”の先頭から4番目の文字は“ト”である。“ラウンド出力”の先頭から4番目の文字は“ド”である。
図11は、パラメータ化情報の例(その1)を示す図である。パラメータ化情報116は、コードクローン、パラメータ数、第1コード置換文字列および第2コード置換文字列の項目を含む。
コードクローンの項目には、コードクローンの識別情報が登録される。パラメータ数の項目には、該当のコードクローンを共通化するときの共通コードにおけるパラメータ数が登録される。第1コード置換文字列の項目には、第1コードにおける置換文字列が登録される。第2コード置換文字列の項目には、第2コードにおける置換文字列が登録される。
例えば、パラメータ化情報116には、コードクローンが“CL1”、パラメータ数が“1”、第1コード置換文字列が“S11A”、第2コード置換文字列が“S12A”という情報が登録される。これは、コードクローン情報CL1におけるコードC11の置換文字列が“S11A”であり、コードC12の置換文字列が“S12A”であり、これらをパラメータ化してコードクローン情報CL1を共通化した場合のパラメータ数が“1”であることを示す。
また、例えば、パラメータ化情報116には、コードクローンが“CL2”、パラメータ数が“1”、第1コード置換文字列が“カウント”、第2コード置換文字列が“ラウンド”という情報が登録される。これは、コードクローン情報CL2におけるコードC21の置換文字列が“カウント”であり、コードC22の置換文字列が“ラウンド”であり、これらをパラメータ化してコードクローン情報CL2を共通化した場合のパラメータ数が“1”であることを示す。
次に、以上のような構成を有するサーバ100の処理手順を説明する。
図12は、サーバの処理例を示すフローチャートである。以下、図12に示す処理をステップ番号に沿って説明する。
(S1)コードクローン検出部120は、ユーザによる比較対象とする複数のソースコードのファイル名の入力を受け付ける。コードクローン検出部120は、記憶部110から該当のファイル名の複数のソースコードを取得し、各ソースコードを比較することで、コードクローンをソースコード毎に検出する。コードクローン検出部120は、コードクローンの検出結果であるコードクローン情報112を生成し、記憶部110に格納する。処理の詳細は、後述される。
(S2)相違単語抽出部130は、記憶部110に記憶されたコードクローン情報112に基づいて、コードクローン間の相違単語を抽出する。相違単語抽出部130は、相違単語の抽出結果である相違単語情報113を生成し、記憶部110に格納する。処理の詳細は、後述される。
(S3)相違文字抽出部140は、記憶部110に記憶された相違単語情報113に基づいて、相違単語間での相違文字の位置(相違位置)を検出する。相違文字抽出部140は、相違位置の検出結果である相違文字情報114を生成し、記憶部110に格納する。処理の詳細は、後述される。
(S4)置換文字列決定部150は、記憶部110に記憶された相違文字情報114に基づいて、相違位置を起点に置換文字列を拡大する。すなわち、置換文字列決定部150は、相違単語において、相違位置を起点として、前後に1文字ずつ置換文字列の候補の文字列範囲を拡大し、所定の条件(置換文字列の決定条件)を基に置換文字列を決定する。ここで用いられる条件は、前述のように、「コードクローンを共通化した際に共通コードにおけるパラメータ数が少なくなる置換文字列を優先する」というものである。処理の詳細は、後述される。
図13は、コードクローン検出例を示すフローチャートである。以下、図13に示す処理をステップ番号に沿って説明する。以下に示す手順は、図12のステップS1に相当する。
(S11)コードクローン検出部120は、記憶部110を参照して、比較対象とする複数のソースコードを読み込む。
(S12)コードクローン検出部120は、読み込んだソースコード内のテキスト情報を単語単位に分割する。ソースコードのテキスト情報では、各単語の間がスペースなどの特定の文字コードにより区切られている。コードクローン検出部120は、テキストに含まれるスペースなどを検出することで、当該スペースなどによって区切られた単語を区別することができる。
(S13)コードクローン検出部120は、単語の匿名化を行う。具体的には、記憶部110は、使用するプログラム言語(第2の実施の形態の例ではCOBOL)に応じた予約語を予め記憶する。コードクローン検出部120は、記憶部110に記憶された当該プログラム言語の予約語以外の単語について、“$名前$”(引用符で囲われていない予約語以外の単語)や“$文字列$”(引用符で囲われた予約語以外の単語)といった情報に置換する。
(S14)コードクローン検出部120は、各ソースコードの匿名化結果に対して単語列を比較し、同一の部分単語列(コードクローン部分)を検出する。例えば、図3でも示したように、コードクローン検出部120は、ソースコードP1,P2に対する匿名化結果であるコードP1a,P2aを比較することで、同一の部分単語列(コード片fr1に相当)を検出する。
(S15)コードクローン検出部120は、ステップS14で検出された単語列に相当するコード片をコードクローン情報112に記録する。ステップS14で挙げた例でいえば、コードクローン検出部120は、コード片fr1に対応するソースコードP1のコードC11、および、コード片fr1に対応するソースコードP2のコードC12を含むコードクローン情報CL1を生成する。コードクローン検出部120は、コードクローン情報CL1を記憶部110に格納する(コードクローン情報CL1をコードクローン情報112に追加するということもできる)。
ここで、ステップS14において、コードクローン検出部120は、例えば次のようにして、匿名化後のコードP1a,P2aを比較し、同一の部分単語列を検出する。
図14は、コードクローン情報の抽出処理の例を示す図である。図14で表される行列において、各行はコードP1aの単語列に含まれる各単語に相当する。また、各列はコードP2aの単語列に含まれる各単語に相当する。コードクローン検出部120は、同じ単語の存在する行列位置を記録する。例えば、同じ単語の存在する行列位置に“1”を、同じ単語の存在しない行列位置に“0”を、それぞれ記録する。そして、コードクローン検出部120は、行列位置の斜め方向に指定数以上同じである箇所(例えば、図14中の範囲fr2に相当する箇所)をコードクローンに相当する部分として検出する。なお、範囲fr2に相当する箇所は、図3で例示したコード片fr1に対応する。コードクローン検出部120は、こうしてコード片fr1を検出し、ソースコードP1,P2から当該コード片fr1に相当する部分を抜き出すことで、コードクローン情報CL1を生成する。コードクローン検出部120は、コードクローン情報CL2を含む他のコードクローン情報も同様の方法により生成することができる。
図15は、相違単語抽出例を示すフローチャートである。以下、図15に示す処理をステップ番号に沿って説明する。以下に示す手順は、図12のステップS2に相当する。なお、以下の説明では、2つのソースコードを比較する場合を例示しているために「単語ペア」との用語を使用しているが、3以上のソースコードを比較する場合には、「単語ペア」を「単語セット」と読み替えることができる。
(S21)相違単語抽出部130は、コードクローン情報112に含まれる全ての単語ペアを処理済であるか否か(すなわち、全ての単語ペアについて以降のステップの処理を実行したか否か)を判定する。全ての単語ペアを処理済である場合、処理を終了する。全ての単語ペアを処理済でない場合、処理をステップS22に進める。例えば、今回、ステップS1の処理により、コードクローン情報112として、コードクローン情報CL1が生成されている場合を考える。この場合、相違単語抽出部130は、コードクローン情報CL1に含まれるコードC11,C12から単語ペアを特定できる。具体的には、コードC11,C12それぞれにおいて共通の箇所に記述され互いに相違する2つの単語を単語ペアとする。より具体的には、図14で示した行列の範囲fr2に含まれる部分のうち、予約語以外の共通箇所に対応するコードC11の単語およびコードC12の単語が単語ペアである。例えば、図14の4行4列目の“$名前$”に相当する箇所について、コードC11では単語“S11Aフラグ”が対応し、コードC12では単語“S12Aフラグ”が対応する。よって、相違単語抽出部130は、単語“S11Aフラグ”および単語“S12Aフラグ”を単語ペアとして特定する。
(S22)相違単語抽出部130は、コードクローン情報112を参照して、未処理の単語ペアを取得する。例えば、相違単語抽出部130は、コードクローン情報CL1を参照して、ステップS21で例示した、単語“S11Aフラグ”および単語“S12Aフラグ”を今回処理対象とする単語ペアとして取得する。
(S23)相違単語抽出部130は、ステップS22で取得した単語ペアの各単語が同じ文字列であるか否かを判定する。同じ文字列である場合、当該単語ペアを相違単語抽出処理に関して処理済として、処理をステップS21に進める。同じ文字列ではない場合、当該単語ペアを相違単語抽出処理に関して処理済として、処理をステップS24に進める。同じ文字列であるか否かの判定は、単語ペアに属する各文字を比較することで行える。文字数、各文字および各文字の並び順の全てが同じであれば同じ文字列であり、何れかが異なれば同じ文字列ではない。単語“S11Aフラグ”および単語“S12Aフラグ”の例では、互いに異なる文字(先頭から3番目の文字が“1”、“2”で互いに異なる)を含むので、同じ文字列ではない。
(S24)相違単語抽出部130は、ステップS23で同じ文字列ではない(すなわち、異なる文字列である)と判定された単語ペアを、相違単語情報113に記録する。例えば、相違単語抽出部130は、当該単語ペアとコードクローン情報112の識別情報とペア識別子とを対応付けた相違単語情報113(あるいは、相違単語情報113のレコードと称してもよい)を生成する。そして、処理をステップS21に進める。
図16は、相違文字抽出例を示すフローチャートである。以下、図16に示す処理をステップ番号に沿って説明する。以下に示す手順は、図12のステップS3に相当する。
(S31)相違文字抽出部140は、相違単語情報113に含まれる全ての単語ペアを処理済であるか否か(すなわち、全ての単語ペアについてステップS32〜S34の処理を実行したか否か)を判定する。全ての単語ペアを処理済である場合、処理を終了する。全ての単語ペアを処理済でない場合、処理をステップS32に進める。例えば、今回、ステップS2の処理により、コードクローン情報CL1に対する相違単語情報113が生成されている場合を考える。この場合、相違文字抽出部140は、相違単語情報113に含まれるコードクローン情報CL1に関するレコードについて、ステップS32〜S34の処理を実行することになる。
(S32)相違文字抽出部140は、相違単語情報113を参照して、未処理の単語ペアを取得する。例えば、相違単語抽出部130は、相違単語情報113を参照して、ステップS31で例示した、コードクローン情報CL1に関する相違単語“S11Aフラグ”および相違単語“S12Aフラグ”を今回処理対象とする単語ペアとして取得する。
(S33)相違文字抽出部140は、単語ペアの各相違単語を1文字ずつ比較し、相違する文字位置を検出する。相違単語“S11Aフラグ”および相違単語“S12Aフラグ”の例では、それぞれ先頭から3番目の文字が“1”、“2”で互いに異なる。このため、相違文字抽出部140は、相違する文字位置(相違位置)を、“3−3”と検出する。
(S34)相違文字抽出部140は、ステップS33で検出した相違する文字位置(相違位置)を、相違文字情報114に記録する。例えば、相違文字抽出部140は、当該相違位置(例えば、“3−3”という情報)とコードクローン情報112の識別情報とペア識別子と各相違単語とを対応付けた相違文字情報114(あるいは、相違文字情報114のレコードと称してもよい)を生成する。相違文字抽出部140は、該当の単語ペアを、相違文字抽出処理に関して処理済にして、処理をステップS31に進める。
図17は、相違文字情報の抽出処理の例を示す図である。例えば、相違文字抽出部140は、既存の方法を用いて、ステップS33における相違文字および相違位置の抽出を行える。
具体的には、まず、2つの文字列に含まれる各文字を縦、横に並べたグラフを用意する。図17の例では、縦方向に文字列“ラウンドフラグ”の各文字を並べ、横方向に文字列“カウントフラグ”の各文字を並べている。この場合、グラフの始点は文字列の先頭側(グラフの左上頂点)である。グラフの終点は文字列の終端側(グラフの右下頂点)である。そして、当該グラフにおいて、同じ文字がある箇所に斜線を引く(相違文字抽出部140は、グラフを表す行列の該当位置に斜線に相当する情報を設定する)。その上で、相違文字抽出部140は、始点から終点に到達する経路の中で、斜線に相当する箇所を最も多く通る経路を探索し、当該経路における斜線以外の部分(図17中の縦横移動の部分)を相違位置と特定する。
こうして、相違文字抽出部140は、例えば、“カウントフラグ”および“ラウンドフラグ”という2つの文字列に対して、相違位置“1−1”(図17の1行1列目に相当)、“4−4”(図17の4行4列目に相当)を取得する。
なお、図17で例示した方法は、例えば、あるソフトウェアによるテキストの差分解析(例えば、UNIX(登録商標)などのOSで利用可能なdiffコマンドなど)でも利用されることがある。
図18は、置換文字列拡大例を示すフローチャートである。以下、図18に示す処理をステップ番号に沿って説明する。以下に示す手順は、図12のステップS4に相当する。
(S41)置換文字列決定部150は、相違文字情報114を参照して、相違文字を置換文字列とする。例えば、今回、コードクローン情報CL1に対して置換文字列を決定する場合、置換文字列決定部150は、相違文字情報114から単語ペアa1,a2に関する相違位置“3−3”を取得する。そして、置換文字列決定部150は、相違単語“S11Aフラグ”、“S12Aフラグ”、“S11A名前”および“S12A名前”について、先頭から3番目の文字を相違文字とする。置換文字列決定部150は、まずは当該相違文字を置換文字列とする。なお、以後、置換文字列が確定されるまでのステップでいう「置換文字列」は、「置換文字列の候補」であると考えてもよい。
(S42)置換文字列決定部150は、置換文字列が単語の先頭を含むか否かを判定する。置換文字列が単語の先頭を含む場合、処理をステップS47に進める。置換文字列が単語の先頭を含まない場合、処理をステップS43に進める。
(S43)置換文字列決定部150は、置換文字列を前方に1文字拡大する。すなわち、置換文字列決定部150は、置換文字列の候補とする文字列範囲を前方に1文字分だけ広げる。より具体的には、置換文字列決定部150は、現在の置換文字列に当該前方の1文字を結合して、当該置換文字列を更新する。なお、拡大の結果、現在拡大している第1の置換文字列が第2の置換文字列と隣接した場合、置換文字列決定部150は、第1および第2の置換文字列を結合して1つの置換文字列とする。
(S44)置換文字列決定部150は、現在の置換文字列をパラメータ化して共通コードを作成するときのパラメータ数を計算する。置換文字列決定部150は、今回計算したパラメータ数を記憶部110に格納する。
(S45)置換文字列決定部150は、今回計算したパラメータ数が、記憶部110に記憶された前回計算したパラメータ数よりも増加したか否かを判定する。増加した場合、処理をステップS46に進める。増加していない場合、処理をステップS42に進める。なお、ステップS45を最初に実行する場合、前回のパラメータ数の計算結果が存在していないので、置換文字列決定部150は、パラメータ数が増加していないと判定して、処理をステップS42に進める。
(S46)置換文字列決定部150は、ステップS43で拡大した置換文字列を元に戻す。すなわち、置換文字列決定部150は、現在の置換文字列の先頭の1文字を除去して、ステップS43で拡大する前の置換文字列に戻す。
(S47)置換文字列決定部150は、置換文字列が単語の末尾を含むか否かを判定する。置換文字列が単語の末尾を含む場合、処理をステップS52に進める。置換文字列が単語の末尾を含まない場合、処理をステップS48に進める。ステップS47 Yesの場合、パラメータ化対象は、現在の置換文字列で確定される。
(S48)置換文字列決定部150は、置換文字列を後方に1文字拡大する。すなわち、置換文字列決定部150は、置換文字列の候補とする文字列範囲を後方に1文字分だけ広げる。より具体的には、置換文字列決定部150は、現在の置換文字列に当該後方の1文字を結合して、当該置換文字列を更新する。なお、拡大の結果、現在拡大している第1の置換文字列が第2の置換文字列と隣接した場合、置換文字列決定部150は、第1および第2の置換文字列を結合して1つの置換文字列とする。
(S49)置換文字列決定部150は、現在の置換文字列をパラメータ化して共通コードを作成するときのパラメータ数を計算する。置換文字列決定部150は、今回計算したパラメータ数を記憶部110に格納する。
(S50)置換文字列決定部150は、今回計算したパラメータ数が、記憶部110に記憶された前回計算したパラメータ数よりも増加したか否かを判定する。増加した場合、処理をステップS51に進める。増加していない場合、処理をステップS47に進める。なお、ステップS45を実行せずにステップS50を最初に実行する場合、前回のパラメータ数の計算結果が存在していないので、置換文字列決定部150は、パラメータ数が増加していないと判定して、処理をステップS47に進める。
(S51)置換文字列決定部150は、ステップS48で拡大した置換文字列を元に戻す。すなわち、置換文字列決定部150は、現在の置換文字列の末尾の1文字を除去して、ステップS48で拡大する前の置換文字列に戻す。パラメータ化対象は、現在の置換文字列で確定される。
(S52)置換文字列決定部150は、パラメータ化対象として確定した置換文字列とパラメータ数とを出力する。具体的には、置換文字列決定部150は、コードクローン情報112の識別情報と各コードクローンにおける置換文字列とパラメータ数とを対応付けたパラメータ化情報116(パラメータ化情報116のレコードと称してもよい)を生成する。置換文字列決定部150は、生成したパラメータ化情報116を記憶部110に格納する。置換文字列決定部150は、パラメータ化情報116の内容をディスプレイ11を用いて表示してもよいし、パラメータ化情報116をネットワーク10を介して他のコンピュータに送信してもよい。
上記の手順によれば、置換文字列決定部150は、置換文字列の複数の候補のうち複数の候補それぞれに応じた共通コードに含まれるパラメータの数が少ない候補を優先的に選択することで、置換文字列を決定しているということができる。
特に、置換文字列決定部150は、当該決定において、相違位置を起点に1文字ずつ置換文字列の候補に対応する文字列範囲を拡大する。そして、置換文字列決定部150は、1文字拡大するたびに共通コードにおけるパラメータの数を計算し、今回のパラメータの数が前回のパラメータの数よりも増えると、前回の文字列範囲を、パラメータ化対象とする置換文字列と決定する。
次に、コードクローン情報CL1,CL2に対するパラメータ化情報の生成例を具体的に説明する。まず、コードクローン情報CL1に対する例を説明する。
図19は、相違文字抽出の第1の具体例を示す図である。相違単語抽出部130は、コードクローン情報CL1を参照して、コードC11,C12それぞれから相違単語を抽出し、相違単語情報(相違単語情報113aとする)を生成する。具体的には、コードC11の相違単語“S11Aフラグ”とコードC12の相違単語“S12Aフラグ”とが相違単語の単語ペアa1である。また、コードC11の相違単語“S11A名前”とコードC12の相違単語“S12A名前”とが相違単語の単語ペアa2である。
そして、相違文字抽出部140は、相違単語情報113aを参照して、各単語ペアに対する相違位置を検出し、相違文字情報(相違文字情報114aとする)を生成する。具体的には、単語ペアa1について、“S11Aフラグ”と“S12Aフラグ”とでは先頭から3番目の文字がそれぞれ相違するので、相違文字抽出部140は、相違位置“3−3”を検出する。また、単語ペアa2について、“S11Aフラグ”と“S12Aフラグ”とでは先頭から3番目の文字がそれぞれ相違するので、相違文字抽出部140は、相違位置“3−3”を検出する。
図20は、置換文字列拡大の第1の具体例を示す図である。置換文字列決定部150は、相違文字情報114aに基づいて、パラメータ化の対象とする置換文字列を決定する。まず、置換文字列決定部150は、単語ペアa1,a2それぞれにおいて、相違文字情報114aで示される相違位置の相違文字を置換文字列とする(ステップST11)。
具体的には、置換文字列決定部150は、単語ペアa1について、“S11Aフラグ”の先頭から3番目の文字“1”を置換文字列とし、“S12Aフラグ”の先頭から3番目の文字“2”を置換文字列とする。また、置換文字列決定部150は、単語ペアa2について、“S11A名前”の先頭から3番目の文字“1”を置換文字列とし、“S12A名前”の先頭から3番目の文字“2”を置換文字列とする。この場合、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“1”である。また、相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“2”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“1”および“2”に対して1つパラメータを用意すればよいからである。
次に、置換文字列決定部150は、前方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の先頭に、相違単語の先頭から2番目の文字を結合して置換文字列を更新する(ステップST12)。
ここでは、各相違単語の先頭から2番目の文字は“1”である。したがって、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“11”である。また、相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“12”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“11”および“12”に対して1つパラメータを用意すればよいからである。
図21は、置換文字列拡大の第1の具体例(続き)を示す図である。次に、置換文字列決定部150は、前方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の先頭に、相違単語の先頭から1番目の文字を結合して置換文字列を更新する(ステップST13)。
ここでは、各相違単語の先頭から1番目の文字は“S”である。したがって、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“S11”である。また、相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“S12”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“S11”および“S12”に対して1つパラメータを用意すればよいからである。
この段階で、各置換文字列は、各相違単語の先頭の文字まで拡大済である(先頭の文字を含んでいる)。このため、以後、置換文字列決定部150は、置換文字列の起点とした相違位置から後方に置換文字列を拡大する。
次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から4番目の文字を結合して置換文字列を更新する(ステップST14)。
ここでは、各相違単語の先頭から4番目の文字は“A”である。したがって、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“S11A”である。また、相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“S12A”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“S11A”および“S12A”に対して1つパラメータを用意すればよいからである。
次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から5番目の文字を結合して置換文字列を更新する(ステップST15)。
ここでは、相違単語“S11Aフラグ”および“S12Aフラグ”の先頭から5番目の文字は“フ”である。また、相違単語“S11A名前”および“S12A名前”の先頭から5番目の文字は“名”である。したがって、相違単語“S11Aフラグ”の置換文字列は“S11Aフ”である。相違単語“S12Aフラグ”の置換文字列は“S12Aフ”である。相違単語“S11A名前”の置換文字列は“S11A名”である。相違単語“S12A名前”の置換文字列は“S12A名”である。各置換文字列をパラメータ化した場合、“S11Aフ”および“S12Aフ”で1つ目のパラメータ、“S11A名”および“S12A名”で2つ目のパラメータを用意することになるので、パラメータ数は“2”である。パラメータ数“2”は、ステップST14におけるパラメータ数“1”よりも多い。
このため、置換文字列決定部150は、ステップST15で特定した置換文字列について1文字分の拡大を元に戻す。すなわち、置換文字列決定部150は、ステップST14で特定した置換文字列“S11A”および“S12A”をパラメータ化対象の置換文字列として確定する。置換文字列決定部150は、当該置換文字列に関するパラメータ化情報116(パラメータ化情報116のレコードと称してもよい)を生成し、記憶部110に格納する。
続いて、コードクローン情報CL2に対するパラメータ化情報の生成例を具体的に説明する。
図22は、相違文字抽出の第2の具体例を示す図である。相違単語抽出部130は、コードクローン情報CL2を参照して、コードC21,C22それぞれから相違単語を抽出し、相違単語情報(相違単語情報113bとする)を生成する。具体的には、コードC21の相違単語“カウントフラグ”とコードC22の相違単語“ラウンドフラグ”とが相違単語の単語ペアb1である。また、コードC21の相違単語“カウント出力”とコードC22の相違単語“ラウンド出力”とが相違単語の単語ペアb2である。
そして、相違文字抽出部140は、相違単語情報113bを参照して、各単語ペアに対する相違位置を検出し、相違文字情報(相違文字情報114bとする)を生成する。具体的には、単語ペアb1について、“カウントフラグ”と“ラウンドフラグ”とでは、先頭から1番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“1−1”を検出する。また、“カウントフラグ”と“ラウンドフラグ”とでは、先頭から4番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“4−4”を検出する。
また、単語ペアb2について、“カウント出力”と“ラウンド出力”とでは、先頭から1番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“1−1”を検出する。また、“カウント出力”と“ラウンド出力”とでは、先頭から4番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“4−4”を検出する。
図23は、置換文字列拡大の第2の具体例を示す図である。置換文字列決定部150は、相違文字情報114bに基づいて、パラメータ化の対象とする置換文字列を決定する。具体的には、まず、置換文字列決定部150は、単語ペアb1,b2それぞれにおいて、相違文字情報114bで示される相違位置の相違文字を置換文字列とする(ステップST21)。
具体的には、置換文字列決定部150は、単語ペアb1について、“カウントフラグ”の先頭から1番目の文字“カ”、および、先頭から4番目の文字“ト”をそれぞれ置換文字列とする。また、置換文字列決定部150は、“ラウンドフラグ”の先頭から1番目の文字“ラ”、および、先頭から4番目の文字“ド”をそれぞれ置換文字列とする。この場合、各置換文字列をパラメータ化しようとすると、置換文字列“カ”および“ラ”に対して1つ目のパラメータ、置換文字列“ト”および“ド”に対して2つ目のパラメータを用意することになるので、パラメータ数は“2”である。
置換文字列決定部150は、拡大を行う置換文字列を決定する。ここでは、各相違文字のうち、先頭側にある文字を優先的に拡大対象として選択する(ただし、末尾側にある文字を優先的に拡大対象として選択してもよい)。この場合、置換文字列決定部150は、相違文字“カ”および“ラ”に対応する置換文字列の拡大を行うと決定する。ここで、相違文字“カ”および“ラ”は、何れも相違単語の先頭の文字である。これ以上前方へは拡大できないので、置換文字列決定部150は、置換文字列を後方へ拡大する。
置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から2番目の文字を結合して置換文字列を更新する(ステップST22)。
ここでは、各相違文字の先頭から2番目の文字は“ウ”である。したがって、相違単語“カウントフラグ”および“カウント出力”それぞれの置換文字列は、“カウ”および“ト”である。また、相違単語“ラウンドフラグ”および“ラウンド出力”それぞれの置換文字列は、“ラウ”および“ド”である。各置換文字列をパラメータ化した場合のパラメータ数は“2”である。置換文字列“カウ”および“ラウ”に対して1つ目のパラメータ、置換文字列“ト”および“ド”に対して2つ目のパラメータを用意することになる(合計2つのパラメータを用意する)からである。
図24は、置換文字列拡大の第2の具体例(続き)を示す図である。次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から3番目の文字を結合して置換文字列を更新する(ステップST23)。
ここでは、各相違単語の先頭から3番目の文字は“ン”である。したがって、相違単語“カウントフラグ”および“カウント出力”それぞれの置換文字列は“カウント”である。ここで、置換文字列決定部150は、今回の拡大によって作成した置換文字列“カウン”と、“カウン”の直後に後続する置換文字列“ト”とを結合して、1つの置換文字列“カウント”とする。また、相違単語“ラウンドフラグ”および“ラウンド出力”それぞれの置換文字列は“ラウンド”である。ここで、置換文字列決定部150は、今回の拡大によって作成した置換文字列“ラウン”と、“ラウン”の直後に後続する置換文字列“ド”とを結合して、1つの置換文字列“ラウンド”とする。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“カウント”および“ラウンド”に対して1つパラメータを用意すればよいからである。
次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から5番目の文字を結合して置換文字列を更新する(ステップST24)。なお、ステップST23で説明したように、先頭から4番目の文字(“ト”または“ド”)は、置換文字列の末尾に既に結合済である。
ここでは、相違単語“カウントフラグ”および“ラウンドフラグ”の先頭から5番目の文字は“フ”である。また、相違単語“カウント出力”および“ラウンド出力”の先頭から5番目の文字は“出”である。したがって、相違単語“カウントフラグ”の置換文字列は“カウントフ”である。相違単語“ラウンドフラグ”の置換文字列は“ラウンドフ”である。相違単語“カウント出力”の置換文字列は“カウント出”である。相違単語“ラウンド出力”の置換文字列は“ラウンド出”である。各置換文字列をパラメータ化した場合、“カウントフ”および“ラウンドフ”で1つ目のパラメータ、“カウント出”および“ラウンド出”で2つ目のパラメータを用意することになるので、パラメータ数は“2”である。パラメータ数“2”は、ステップST23におけるパラメータ数“1”よりも多い。
このため、置換文字列決定部150は、ステップST24で特定した置換文字列について1文字分の拡大を元に戻す。すなわち、置換文字列決定部150は、ステップST23で特定した置換文字列“カウント”および“ラウンド”をパラメータ化対象の置換文字列として確定する。置換文字列決定部150は、当該置換文字列に関するパラメータ化情報116(パラメータ化情報116のレコードと称してもよい)を生成し、記憶部110に格納する。
置換文字列決定部150は、パラメータ化情報116を参照して、コードクローン情報に含まれる各コード、および、各コードそれぞれの置換文字列に基づいて、各コードの置換文字列をパラメータに置換した共通コードを出力することもできる。
図25は、コードクローン共通化の例(その1)を示す図である。例えば、置換文字列決定部150は、パラメータ化情報116に基づいて、コードC11,C12を共通化した共通コードC1aを生成してもよい。ここで、パラメータ化情報116aは、パラメータ化情報116のコードクローン情報CL1に対応する情報の一部を示している。
パラメータ化情報116aによれば、コードC11の置換文字列は“S11A”である。また、コードC12の置換文字列は“S12A”である。したがって、置換文字列決定部150は、コードC11に含まれる置換文字列“S11A”、および、コードC12に含まれる置換文字列“S12A”それぞれをプレースホルダ(例えば、“????”)に置換した共通コードC1aを生成する。共通コードC1aのファイル名を“COMMON11.CBL”とする。
すると、置換文字列決定部150は、ソースコードP1,P2のコードクローンに相当する部分を、共通コードC1aを呼び出す記述に書き換えることができる。例えば、ソースコードP1の該当のコードクローン部分を、共通コードC1aの呼び出し(コピー)、および、パラメータに相当するプレースホルダへの文字列“S11A”の設定、を行う記述に置換できる。より具体的には、ソースコードP1におけるコードC11の部分を、“COPY COMMON11 REPLACING ==????== BY ==S11A==”という記述に置換できる。ソースコードPs1は、ソースコードP1に対する当該置換後の記述を示す。
同様に、置換文字列決定部150は、ソースコードP2の該当のコードクローン部分を、共通コードC1aの呼び出し(コピー)、および、パラメータに相当するプレースホルダへの文字列“S12A”の設定、を行う記述に置換できる。より具体的には、ソースコードP2におけるコードC12の部分を、“COPY COMMON11 REPLACING ==????== BY ==S12A==”という記述に置換できる。ソースコードPs2は、ソースコードP2に対する当該置換後の記述を示す。
このようにすると、例えば、「S21Bフラグ」など、“フラグ”の文字列の前方にフラグを修飾するような語が付加された変数名が追加されても、共通コードC1aをそのまま再利用できる。すなわち、共通コードC1aは、相違箇所のみをパラメータ化して作成した共通コードCn1(図4で例示)に比べて、再利用可能性が高い。
図26は、コードクローン共通化の例(その2)を示す図である。例えば、置換文字列決定部150は、パラメータ化情報116に基づいて、コードC21,C22を共通化した共通コードC2aを生成してもよい。ここで、パラメータ化情報116bは、パラメータ化情報116のコードクローン情報CL2に対応する情報の一部を示している。
パラメータ化情報116bによれば、コードC21の置換文字列は“カウント”である。また、コードC22の置換文字列は“ラウンド”である。したがって、置換文字列決定部150は、コードC21に含まれる置換文字列“カウント”、および、コードC22に含まれる置換文字列“ラウンド”それぞれをプレースホルダ(例えば、“XXXX”)に置換した共通コードC2aを生成する。共通コードC2aのファイル名を“COMMON12.CBL”とする。
すると、置換文字列決定部150は、ソースコードP3,P4のコードクローンに相当する部分を、共通コードC2aを呼び出す記述に書き換えることができる。例えば、ソースコードP3の該当のコードクローン部分を、共通コードC2aの呼び出し、および、パラメータに相当するプレースホルダへの文字列“カウント”の設定、を行う記述に置換できる。より具体的には、ソースコードP3におけるコードC21の部分を、“COPY COMMON12 REPLACING ==XXXX== BY ==カウント==”という記述に置換できる。ソースコードPs3は、ソースコードP3に対する当該置換後の記述を示す。
同様に、置換文字列決定部150は、ソースコードP4の該当のコードクローン部分を、共通コードC2aの呼び出し、および、パラメータに相当するプレースホルダへの文字列“ラウンド”の設定、を行う記述に置換できる。より具体的には、ソースコードP4におけるコードC22の部分を、“COPY COMMON12 REPLACING ==XXXX== BY ==ラウンド==”という記述に置換できる。ソースコードPs4は、ソースコードP4に対する当該置換後の記述を示す。
このように意味のある文字列の単位をパラメータ化することで、ソフトウェア開発を行うユーザにとって、置換される文字の意味が分かりやすい共通コードを提供できる。すなわち、共通コードC2aは、相違箇所のみをパラメータ化して作成した共通コードCn2(図5で例示)に比べて可読性が高い。
以上のように、サーバ100によれば、共通コードの可読性、および、再利用可能性を高め、ユーザによるプログラムの作成や保守に伴う作業を省力化できる。こうして、サーバ100は、ソフトウェア開発の効率を改善することができる。
ところで、置換文字列決定部150は、置換文字列の決定に補助情報115を用いてもよい。例えば、補助情報115は、ユーザにより記憶部110に予め格納される。
図27は、補助情報の例を示す図である。補助情報115は、置換文字列を決定するための補助的な条件を示す情報である。具体的には、補助情報115は、置換文字列を決定するための補助的な検出条件として、区切り文字や文字種類の境界という情報を含む。区切り文字とは、例えば、ハイフン記号“−”、スラッシュ記号“/”およびピリオド記号“.”などである。また、文字種類の境界とは、アルファベットの大文字/小文字の変化点、アルファベット/数字の変化点、平仮名/アルファベットの変化点、平仮名/カタカナの変化点、カタカナ/漢字の変化点など、文字の種類が変更される境界である。
例えば、置換文字列決定部150は、図18のステップS45 Noの場合、および、同ステップS50 Noの場合に、補助情報115に基づく条件判断を行う。具体的には、ステップS45 No、かつ、今回の置換文字列の拡大により、補助情報115で指定された区切り文字に達した場合、置換文字列決定部150は、処理をステップS46に進める。一方、ステップS45 No、かつ、今回の置換文字列の拡大により、補助情報115で指定された区切り文字に達していない場合、置換文字列決定部150は、処理をステップS42に進める。
また、例えば、ステップS50 No、かつ、今回の置換文字列の拡大により、補助情報115で指定された区切り文字に達した場合、置換文字列決定部150は、処理をステップS51に進める。一方、ステップS50 No、かつ、今回の置換文字列の拡大により、補助情報115で指定された区切り文字に達していない場合、置換文字列決定部150は、処理をステップS47に進める。ここで、上記の「区切り文字に達しているか否か」の判定は、今回の置換文字列の拡大により「文字種類の境界を検出したか否か」と読み替えてもよい。
次に、置換文字列決定部150による、補助情報115に基づくパラメータ化情報の生成の具体例を説明する。
図28は、相違文字抽出の第3の具体例を示す図である。ここでは、コードクローン情報CL3を例示して、パラメータ化情報を生成する処理を説明する。コードクローン情報CL3は、コードC31,C32を含む。コードC31は、変数名を示す単語“S11A−フラグ”(1行目)、および、変数名を示す単語“S11A−名前”(2行目)を含む。コードC32は、変数名を示す単語“S12A−フラグ”(1行目)、および、変数名を示す単語“S12A−名前”(2行目)を含む。
相違単語抽出部130は、コードクローン情報CL3を参照して、コードC31,C32それぞれから相違単語を抽出し、相違単語情報(相違単語情報113cとする)を生成する。具体的には、コードC31の相違単語“S11A−フラグ”とコードC32の相違単語“S12A−フラグ”とが相違単語の単語ペアc1である。また、コードC31の相違単語“S11A−名前”とコードC32の相違単語“S12A−名前”とが相違単語の単語ペアc2である。
そして、相違文字抽出部140は、相違単語情報113cを参照して、各単語ペアに対する相違位置を検出し、相違文字情報(相違文字情報114cとする)を生成する。具体的には、単語ペアc1について、“S11A−フラグ”と“S12A−フラグ”とでは先頭から3番目の文字がそれぞれ相違するので、相違文字抽出部140は、相違位置“3−3”を検出する。また、単語ペアc2について、“S11A−名前”と“S12A−名前”とでは先頭から3番目の文字がそれぞれ相違するので、相違文字抽出部140は、相違位置“3−3”を検出する。
図29は、置換文字列拡大の第3の具体例を示す図である。置換文字列決定部150は、相違文字情報114cに基づいて、パラメータ化の対象とする置換文字列を決定する。まず、置換文字列決定部150は、単語ペアc1,c2それぞれにおいて、相違文字情報114cで示される相違位置の相違文字を置換文字列とする(ステップST31)。
具体的には、置換文字列決定部150は、単語ペアc1について、“S11A−フラグ”の先頭から3番目の文字“1”を置換文字列とし、“S12A−フラグ”の先頭から3番目の文字“2”を置換文字列とする。また、置換文字列決定部150は、単語ペアc2について、“S11A−名前”の先頭から3番目の文字“1”を置換文字列とし、“S12A−名前”の先頭から3番目の文字“2”を置換文字列とする。この場合、相違単語“S11A−フラグ”および“S11A−名前”それぞれの置換文字列は“1”である。また、相違単語“S12A−フラグ”および“S12A−名前”それぞれの置換文字列は“2”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“1”および“2”に対して1つパラメータを用意すればよいからである。
続いて、置換文字列決定部150は、図20のステップST12〜図21のステップST14と同様に、置換文字列を“S11A”および“S12A”まで拡大する。置換文字列を“S11A”および“S12A”とした場合のパラメータ数は“1”である。
次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から5文字目の文字を結合して置換文字列を更新する。ここで、各相違単語の先頭から5文字目の文字はハイフン“−”である。このため、置換文字列決定部150は、補助情報115で指定されるハイフンが置換文字列に結合されたことを検出する。なお、更新後の置換文字列でパラメータ化した場合のパラメータ数は“1”であり、更新前と変わらない。
すると、置換文字列決定部150は、置換文字列に対する今回の拡大分を元に戻し、“S11A”および“S12A”をパラメータ化対象の置換文字列として確定する(ステップST32)。置換文字列決定部150は、当該置換文字列に関するパラメータ化情報116を生成し、記憶部110に格納する。
更に、以下では文字の種類の境界を検出して置換文字列を決定する具体例を説明する。
図30は、相違文字抽出の第4の具体例を示す図である。ここでは、コードクローン情報CL4を例示して、パラメータ化情報を生成する処理を説明する。コードクローン情報CL4は、コードC41,C42を含む。コードC41は、変数名を示す単語“PGXX入力フラグ”(1行目)、および、変数名を示す単語“PGXX入力番号”(2行目)を含む。コードC42は、変数名を示す単語“PGYX入力フラグ”(1行目)、および、変数名を示す単語“PGYX入力番号”(2行目)を含む。
相違単語抽出部130は、コードクローン情報CL4を参照して、コードC41,C42それぞれから相違単語を抽出し、相違単語情報(相違単語情報113dとする)を生成する。具体的には、コードC41の相違単語“PGXX入力フラグ”とコードC42の相違単語“PGYX入力フラグ”とが相違単語の単語ペアd1である。また、コードC41の相違単語“PGXX入力番号”とコードC42の相違単語“PGYX入力番号”とが相違単語の単語ペアd2である。
そして、相違文字抽出部140は、相違単語情報113dを参照して、各単語ペアに対する相違位置を検出し、相違文字情報(相違文字情報114dとする)を生成する。具体的には、単語ペアd1について、“PGXX入力フラグ”と“PGYX入力フラグ”とでは先頭から3番目の文字がそれぞれ相違するので、相違文字抽出部140は、相違位置“3−3”を検出する。また、単語ペアd2について、“PGXX入力番号”と“PGYX入力番号”とでは先頭から3番目の文字がそれぞれ相違するので、相違文字抽出部140は、相違位置“3−3”を検出する。
図31は、置換文字列拡大の第4の具体例を示す図である。置換文字列決定部150は、相違文字情報114dに基づいて、パラメータ化の対象とする置換文字列を決定する。まず、置換文字列決定部150は、単語ペアd1,d2それぞれにおいて、相違文字情報114dで示される相違位置の相違文字を置換文字列とする(ステップST41)。
具体的には、置換文字列決定部150は、単語ペアd1について、“PGXX入力フラグ”の先頭から3番目の文字“X”を置換文字列とし、“PGYX入力フラグ”の先頭から3番目の文字“Y”を置換文字列とする。また、置換文字列決定部150は、単語ペアd2について、“PGXX入力番号”の先頭から3番目の文字“X”を置換文字列とし、“PGYX入力番号”の先頭から3番目の文字“Y”を置換文字列とする。この場合、相違単語“PGXX入力フラグ”および“PGXX入力番号”それぞれの置換文字列は“X”である。また、相違単語“PGYX入力番号”および“PGYX入力番号”それぞれの置換文字列は“Y”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“X”および“Y”に対して1つパラメータを用意すればよいからである。
続いて、置換文字列決定部150は、相違位置を起点に前後に置換文字列を拡大することで、置換文字列を“PGXX”および“PGYX”まで拡大する(ステップST42)。置換文字列を“PGXX”および“PGYX”とした場合のパラメータ数は“1”である。
次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から5文字目の文字を結合して置換文字列を更新する。ここで、各相違単語の先頭から5文字目の文字は“入”である。置換文字列決定部150は、補助情報115で指定される文字の種類の境界(ここでは、アルファベットから漢字への変更)を検出する。なお、更新後の置換文字列でパラメータ化した場合のパラメータ数は“1”で、更新前と変わらない。
すると、置換文字列決定部150は、置換文字列に対する今回の拡大分を元に戻し、“PGXX”および“PGYX”をパラメータ化対象の置換文字列として確定する(ステップST43)。置換文字列決定部150は、当該置換文字列に関するパラメータ化情報116を生成し、記憶部110に格納する。
図32は、パラメータ化情報の例(その2)を示す図である。パラメータ化情報116aは、図29,図31で例示した手順により生成されたパラメータ化情報を示している。
例えば、置換文字列決定部150は、コードクローン情報CL3に対して、パラメータ数“1”、第1コード(コードC31)の置換文字列“S11A”および第2コード(コードC32)の置換文字列“S12A”を登録する。
また、置換文字列決定部150は、コードクローン情報CL4に対して、パラメータ数“1”、第1コード(コードC41)の置換文字列“PGXX”および第2コード(コードC42)の置換文字列“PGYX”を登録する。
このように、置換文字列決定部150は、パラメータ数の条件に加え、複数の相違単語それぞれに含まれる所定の文字または隣接する文字の種類の変化に応じて置換文字列を決定する。より具体的には、置換文字列決定部150は、補助情報115を用いることで、パラメータ数が増加しない範囲で、区切り文字や文字の種類の境界まで置換文字列に相当する文字列範囲を広げることができる。
ここで、区切り文字を用いた表記や文字の種類の変更は、変数名や処理名(例えば、関数名、オブジェクト名、または、サブルーチン名)などにおいて、変数名に含まれる各単語の意味的な区切りを表すために用いられることが多い。このため、意味的な区切りのある部分で置換文字列の範囲も区切ることで、ユーザにとって可読性や再利用可能性の高いパラメータ化を実現できる。
また、置換文字列決定部150は、補助情報115に代えて、あるいは、補助情報115に加えて、辞書情報115aを更に用いてもよい。
図33は、辞書情報の例を示す図である。例えば、辞書情報115aは、記憶部110に予め格納される。辞書情報115aは、変数名や処理名などに使用され得る単語の一覧である。例えば、辞書情報115aは、“フラグ”や“名前”など、ユーザが意味を理解できる複数の単語を含む。次に、前述の単語ペアa1,a2を例に挙げて、辞書情報115aを用いた置換文字列拡大の具体例を説明する。
図34は、置換文字列拡大の第5の具体例を示す図である。図20のステップST11と同様に、置換文字列決定部150は、相違文字情報114aに基づいて、パラメータ化の対象とする置換文字列を決定する。具体的には、まず、置換文字列決定部150は、単語ペアa1,a2それぞれにおいて、相違文字情報114aで示される相違位置の相違文字を置換文字列とする(ステップST51)。
このとき、置換文字列決定部150は、記憶部110に格納された辞書情報115aを参照して、単語ペアa1,a2それぞれに含まれる文字列の中から、辞書情報115aに含まれる単語を特定する。単語ペアa1の例では、相違単語“S11Aフラグ”および“S12Aフラグ”は、辞書情報115aに含まれる単語“フラグ”を含む。単語ペアa2の例では、相違単語“S11A名前”および“S12A名前”は、辞書情報115aに含まれる単語“名前”を含む。
したがって、置換文字列決定部150は、単語ペアa1の各相違単語について、“フラグ”の文字列の直前および直後(ただし、“フラグ”は各相違単語の末尾なので直後は考慮しなくてよい)までの文字を、置換文字列の拡大範囲の限界点とする。具体的には、単語ペアa1について、文字“フ”の直前の文字“A”までが置換文字列の拡大範囲の限界点となる。
同様に、置換文字列決定部150は、単語ペアa2の各相違単語について、“名前”の文字列の直前および直後(ただし、“名前”は各相違単語の末尾なので直後は考慮しなくてよい)までの文字を、置換文字列の拡大範囲の限界点とする。具体的には、単語ペアa2について、文字“名”の直前の文字“A”までが置換文字列の拡大範囲の限界点となる。
そして、置換文字列決定部150は、図20のステップST12〜図21のステップST14と同様に、置換文字列を“S11A”および“S12A”まで拡大する。置換文字列を“S11A”および“S12A”とした場合のパラメータ数は“1”である。
ここで、置換文字列を“S11A”および“S12A”の末尾の“A”は、置換文字列の拡大範囲の限界点であるため、置換文字列決定部150は、当該文字“A”よりも後方への置換文字列の拡大を行わない。このため、置換文字列決定部150は、“S11A”および“S12A”をパラメータ化対象の置換文字列として確定する(ステップST52)。置換文字列決定部150は、当該置換文字列に関するパラメータ化情報116を生成し、記憶部110に格納する。このように、置換文字列決定部150は、辞書情報115aを用いて、パラメータ化情報116を生成してもよい。例えば、置換文字列決定部150は、辞書情報115aに登録された所定単語を複数の相違単語に含まれる文字列の中から特定し、複数の相違単語のうち所定単語以外の部分から置換文字列を決定する。こうして、ユーザにとって意味のある単語で区切ってパラメータ化する置換文字列を決定することで、共通コードの可読性や再利用可能性を高めることができる。
なお、ここまでの例では、単語ペアに含まれる各相違単語の文字数が同じ場合を主に説明したが、単語ペアに含まれる各相違単語の文字数は互いに異なっていてもよい。そこで、次に、単語ペアに含まれる各相違単語の文字数が異なる場合を例示する。
図35は、異なる文字数の相違単語を含むソースコードの例を示す図である。ソースコード群111は、更に、ソースコードP5,P6を含む。ソースコードP5のファイル名は“PROG005.CBL”である。ソースコードP6のファイル名は“PROG006.CBL”である。例えば、ソースコードP5の2行目に含まれる単語“カウンターフラグ”と、ソースコードP6の2行目に含まれる単語“ラウンドフラグ”とでは文字数が異なっている。
図36は、異なる文字数の相違単語を含むコードクローン情報の例を示す図である。例えば、コードクローン検出部120は、ユーザによりソースコードP5,P6のファイル名の入力を受け付けると、記憶部110に記憶されたソースコードP5,P6を比較して、コードクローン情報CL5を生成する。
コードクローン情報CL5は、コードC51,C52を含む。コードC51は、ソースコードP5の一部分である。コードC51は、コードC52に類似するコードであり、ソースコードP5,P6の比較に応じて検出されたコードクローンである。コードC52は、ソースコードP6の一部分である。コードC52は、コードC51に類似するコードであり、ソースコードP5,P6の比較に応じて検出されたコードクローンである。
図37は、異なる文字数の相違単語を含む相違単語情報の例を示す図である。相違単語情報113eは、コードクローン情報CL5に対して、相違単語抽出部130により生成される相違単語情報を例示している。
相違単語抽出部130は、コードクローン情報CL5を参照して、コードC51,C52それぞれから相違単語を抽出し、相違単語情報113eを生成する。具体的には、コードC51の相違単語“カウンターフラグ”とコードC52の相違単語“ラウンドフラグ”とが相違単語の単語ペアe1である。また、コードC51の相違単語“カウンター出力”とコードC52の相違単語“ラウンド出力”とが相違単語の単語ペアe2である。
図38は、異なる文字数の相違単語を含む相違文字情報の例を示す図である。相違文字情報114eは、相違単語情報113eに対して、相違文字抽出部140により生成された相違文字情報を例示している。
相違文字抽出部140は、相違単語情報113eを参照して、各単語ペアに対する相違位置を検出し、相違文字情報114eを生成する。具体的には、単語ペアe1について、“カウンターフラグ”と“ラウンドフラグ”とでは、先頭から1番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“1−1”を検出する。また、“カウンターフラグ”と“ラウンドフラグ”とでは、“カウンターフラグ”の先頭から4番目の文字および4番目に後続する5番目の文字(“ター”)と、“ラウンドフラグ”の先頭から4番目の文字(“ド”)とが相違する。このため、相違文字抽出部140は、相違位置“(4,5)−4”を検出する。ここで、相違位置の表記において、かっこ記号“()”で括られた複数の数値は、1つの相違単語に含まれる複数の文字位置を示す。すなわち、相違位置“(4,5)−4”の表記は、相違文字“カウンターフラグ”の先頭から4番目および5番目の連続する2つの文字と、相違文字“ラウンドフラグ”の先頭から4番目の文字と、が相違していることを示している。
単語ペアe2について、“カウンター出力”と“ラウンド出力”とでは、先頭から1番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“1−1”を検出する。また、“カウンター出力”と“ラウンド出力”とでは、“カウンターフラグ”の先頭から4番目の文字および4番目に後続する5番目の文字と、“ラウンドフラグ”の先頭から4番目の文字とが相違する。このため、相違文字抽出部140は、相違位置“(4,5)−4”を検出する。
次に、相違文字情報114eに基づく置換文字列の拡大処理の具体例を説明する。
図39は、置換文字列拡大の第6の具体例を示す図である。置換文字列決定部150は、相違文字情報114eに基づいて、パラメータ化の対象とする置換文字列を決定する。まず、置換文字列決定部150は、単語ペアe1,e2それぞれにおいて、相違文字情報114eで示される相違位置の相違文字を置換文字列とする(ステップST61)。
具体的には、置換文字列決定部150は、単語ペアe1について、“カウンターフラグ”の先頭から1番目の文字“カ”、および、先頭から4番目、5番目の文字“ター”をそれぞれ置換文字列とする。また、置換文字列決定部150は、“ラウンドフラグ”の先頭から1番目の文字“ラ”、および、先頭から4番目の文字“ド”をそれぞれ置換文字列とする。この場合、各置換文字列をパラメータ化しようとすると、置換文字列“カ”および“ラ”に対して1つ目のパラメータ、置換文字列“ター”および“ド”に対して2つ目のパラメータを用意することになるので、パラメータ数は“2”である。
置換文字列決定部150は、拡大を行う置換文字列を決定する。例えば、前述のように、置換文字列決定部150は、各相違文字列のうち、先頭側にある文字を優先的に拡大対象として選択する。この場合、置換文字列決定部150は、相違文字“カ”および“ラ”に対応する置換文字列の拡大を行うと決定する。ここで、相違文字“カ”および“ラ”は、何れも相違単語の先頭の文字である。これ以上前方へは拡大できないので、置換文字列決定部150は、当該置換文字列を後方へ拡大する。
置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から2番目の文字を結合して置換文字列を更新する(ステップST62)。
ここでは、各相違文字の先頭から2番目の文字は“ウ”である。したがって、相違単語“カウンターフラグ”および“カウンター出力”それぞれの置換文字列は、“カウ”および“ター”である。また、相違単語“ラウンドフラグ”および“ラウンド出力”それぞれの置換文字列は、“ラウ”および“ド”である。各置換文字列をパラメータ化した場合のパラメータ数は“2”である。置換文字列“カウ”および“ラウ”に対して1つ目のパラメータ、置換文字列“ター”および“ド”に対して2つ目のパラメータを用意することになるからである。
図40は、置換文字列拡大の第6の具体例(続き)を示す図である。次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から3番目の文字を結合して置換文字列を更新する(ステップST63)。
ここでは、各相違単語の先頭から3番目の文字は“ン”である。したがって、相違単語“カウンターフラグ”および“カウンター出力”それぞれの置換文字列は“カウンター”である。ここで、置換文字列決定部150は、今回の拡大によって作成した置換文字列“カウン”と、“カウン”の直後に後続する置換文字列“ター”とを結合して、1つの置換文字列“カウンター”とする。また、相違単語“ラウンドフラグ”および“ラウンド出力”それぞれの置換文字列は“ラウンド”である。ここで、置換文字列決定部150は、今回の拡大によって作成した置換文字列“ラウン”と、“ラウン”の直後に後続する置換文字列“ド”とを結合して、1つの置換文字列“ラウンド”とする。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“カウンター”および“ラウンド”に対して1つパラメータを用意すればよいからである。
次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列“カウンター”の末尾に、相違単語“カウンターフラグ”および“カウンター出力”それぞれの先頭から6番目の各文字を結合して当該置換文字列を更新する。また、置換文字列決定部150は、現在の置換文字列“ラウンド”の末尾に、相違単語“ラウンドフラグ”および“ラウンド出力”それぞれの先頭から5番目の各文字を結合して当該置換文字列を更新する(ステップST64)。
ここでは、相違単語“カウンターフラグ”の先頭から6番目の文字、および、相違単語“ラウンドフラグ”の先頭から5番目の文字は、“フ”である。相違単語“カウンター出力”の先頭から6番目の文字、および、相違単語“ラウンド出力”の先頭から5番目の文字は、“出”である。したがって、相違単語“カウンターフラグ”の置換文字列は“カウンターフ”である。相違単語“ラウンドフラグ”の置換文字列は“ラウンドフ”である。相違単語“カウンター出力”の置換文字列は“カウンター出”である。相違単語“ラウンド出力”の置換文字列は“ラウンド出”である。各置換文字列をパラメータ化した場合、“カウンターフ”および“ラウンドフ”で1つ目のパラメータ、“カウンター出”および“ラウンド出”で2つ目のパラメータを用意することになるので、パラメータ数は“2”である。パラメータ数“2”は、ステップST63におけるパラメータ数“1”よりも多い。
このため、置換文字列決定部150は、ステップST64で特定した置換文字列について1文字分の拡大を元に戻す。すなわち、置換文字列決定部150は、ステップST63で特定した置換文字列“カウンター”および“ラウンド”をパラメータ化対象の置換文字列として確定する。置換文字列決定部150は、当該置換文字列に関するパラメータ化情報116(パラメータ化情報116のレコードと称してもよい)を生成し、記憶部110に格納する。
図41は、パラメータ化情報の例(その3)を示す図である。パラメータ化情報116bは、図40の処理に応じて置換文字列決定部150により生成されるパラメータ化情報を例示している。パラメータ化情報116bは、コードクローン情報CL5に対して、パラメータ数“1”、コードC51(第1コード)に対する置換文字列“カウンター”、コードC52(第2コード)に対する置換文字列“ラウンド”という情報を含む。
このように、置換文字列決定部150は、ある単語ペアに属する各相違単語の文字数が異なっていても、可読性および再利用可能性の高い共通コードを実現するパラメータ化を行える。
更に、ここまでの説明では、サーバ100における、2つのソースコードの指定に応じたパラメータ化を例示した。ただし、ユーザは3以上のソースコードをサーバ100に指定することもできる。そこで、以下では、一例として、3つのソースコードが指定される場合を説明する。
図42は、3つのソースコードの例を示す図である。ソースコード群111は、更に、ソースコードP7,P8,P9を含む。ソースコードP7のファイル名は“PROG007.CBL”である。ソースコードP8のファイル名は“PROG008.CBL”である。ソースコードP9のファイル名は“PROG009.CBL”である。
図43は、3つの類似コードに関するコードクローン情報の例を示す図である。例えば、コードクローン検出部120は、ユーザによりソースコードP7,P8,P9のファイル名の入力を受け付けると、記憶部110に記憶されたソースコードP7,P8,P9を比較して、コードクローン情報CL6を生成する。コードクローン情報CL6は、コードC61,C62,C63を含む。
コードC61は、ソースコードP7の一部分である。コードC61は、コードC62に類似するコードであり、ソースコードP7,P8の比較に応じて検出されたコードクローンである。コードC61は、コードC63にも類似する。コードクローン検出部120は、ソースコードP7,P9の比較に応じて、コードC61を検出してもよい。
コードC62は、ソースコードP8の一部分である。コードC62は、コードC61に類似するコードであり、ソースコードP7,P8の比較に応じて検出されたコードクローンである。コードC62は、コードC63にも類似する。コードクローン検出部120は、ソースコードP8,P9の比較に応じて、コードC62を検出してもよい。
コードC63は、ソースコードP9の一部分である。コードC63は、コードC61に類似するコードであり、ソースコードP7,P9の比較に応じて検出されたコードクローンである。コードC63は、コードC62にも類似する。コードクローン検出部120は、ソースコードP8,P9の比較に応じて、コードC63を検出してもよい。
図44は、3つの類似コードに関する相違単語情報の例を示す図である。相違単語情報113fは、コードクローン情報CL6に対して、相違単語抽出部130により生成される相違単語情報を例示している。
相違単語抽出部130は、コードクローン情報CL6を参照して、コードC61,C62,C63それぞれから相違単語を抽出し、相違単語情報113fを生成する。この場合、相違単語の1つの組み合わせには3つの相違単語が属する。相違単語の1つの組み合わせは、セット識別子(単語セットf1など)によって識別される。
具体的には、コードC61の相違単語“S11Aフラグ”とコードC62の相違単語“S12Aフラグ”とコードC63の相違単語“S13Aフラグ”とが、単語セットf1の組み合わせに属する相違単語である。
また、コードC61の相違単語“S11A名前”とコードC62の相違単語“S12A名前”とコードC63の相違単語“S13A名前”とが、単語セットf2の組み合わせに属する相違単語である。
相違単語抽出部130は、2つのソースコードが指定された場合と同様に、互いに類似するコードC61,C62,C63それぞれにおいて、共通の箇所に記述され互いに相違する変数名や処理名などを検出することで、各相違単語を抽出することができる。
図45は、3つの類似コードに関する相違文字情報の例を示す図である。相違文字情報114fは、相違単語情報113fに対して、相違文字抽出部140により生成された相違文字情報を例示している。相違文字抽出部140は、相違単語情報113fを参照して、各単語セットに対する相違位置を検出し、相違文字情報114fを生成する。
具体的には、単語セットf1について、“S11Aフラグ”と“S12Aフラグ”とでは、先頭から3番目の文字がそれぞれ相違する。また、“S12Aフラグ”と“S13Aフラグ”とでは、先頭から3番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“3−3−3”を検出する。
単語セットf2について、“S11A名前”と“S12A名前”とでは、先頭から3番目の文字がそれぞれ相違する。また、“S12A名前”と“S13A名前”とでは、先頭から3番目の文字がそれぞれ相違する。このため、相違文字抽出部140は、相違位置“3−3−3”を検出する。
なお、相違文字抽出部140は、ある単語セットに属する3以上の相違文字のうち、比較対象とする2つの相違文字を任意の組み合わせとすることができる。例えば、単語セットf1において、“S11Aフラグ”と“S12Aフラグ”とを比較し、“S11Aフラグ”と“S13Aフラグ”とを比較して、両相違単語の相違位置を検出してもよい。
図46は、置換文字列拡大の第7の具体例を示す図である。置換文字列決定部150は、相違文字情報114fに基づいて、パラメータ化の対象とする置換文字列を決定する。まず、置換文字列決定部150は、単語セットf1,f2それぞれにおいて、相違文字情報114fで示される相違位置の相違文字を置換文字列とする(ステップST71)。
具体的には、置換文字列決定部150は、単語セットf1について、“S11Aフラグ”の先頭から3番目の文字“1”、“S12Aフラグ”の先頭から3番目の文字“2”、および、“S13Aフラグ”の先頭から3番目の文字“3”をそれぞれ置換文字列とする。
また、置換文字列決定部150は、単語セットf2について、“S11A名前”の先頭から3番目の文字“1”、“S12A名前”の先頭から3番目の文字“2”、および、“S13A名前”の先頭から3番目の文字“3”をそれぞれ置換文字列とする。
この場合、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“1”である。相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“2”である。相違単語“S13Aフラグ”および“S13A名前”それぞれの置換文字列は“3”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“1”、“2”、“3”に対して1つパラメータを用意すればよいからである。
次に、置換文字列決定部150は、前方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の先頭に、相違単語の先頭から2番目の文字を結合して置換文字列を更新する(ステップST72)。
ここでは、各相違単語の先頭から2番目の文字は“1”である。したがって、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“11”である。また、相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“12”である。更に、相違単語““13Aフラグ”および“S13A名前”それぞれの置換文字列は“13”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“11”、“12”および“13”に対して1つパラメータを用意すればよいからである。
図47は、置換文字列拡大の第7の具体例(続き)を示す図である。次に、置換文字列決定部150は、前方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の先頭に、相違単語の先頭から1番目の文字を結合して置換文字列を更新する(ステップST73)。
ここでは、各相違単語の先頭から1番目の文字は“S”である。したがって、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“S11”である。また、相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“S12”である。更に、相違単語“S13Aフラグ”および“S13A名前”それぞれの置換文字列は“S13”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“S11”、“S12”および“S13”に対して1つパラメータを用意すればよいからである。
この段階で、各置換文字列は、各相違文字列の先頭の文字まで拡大済である(先頭の文字を含んでいる)。このため、以後、置換文字列決定部150は、置換文字列の起点とした相違位置から後方に置換文字列を拡大する。
次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から4番目の文字を結合して置換文字列を更新する(ステップST74)。
ここでは、各相違単語の先頭から4番目の文字は“A”である。したがって、相違単語“S11Aフラグ”および“S11A名前”それぞれの置換文字列は“S11A”である。相違単語“S12Aフラグ”および“S12A名前”それぞれの置換文字列は“S12A”である。相違単語“S13Aフラグ”および“S13A名前”それぞれの置換文字列は“S13A”である。各置換文字列をパラメータ化した場合のパラメータ数は“1”である。置換文字列“S11A”、“S12A”および“S13A”に対して1つパラメータを用意すればよいからである。
図48は、置換文字列拡大の第7の具体例(続き)を示す図である。次に、置換文字列決定部150は、後方に1文字分、置換文字列の範囲を広げる。すなわち、置換文字列決定部150は、現在の置換文字列の末尾に、相違単語の先頭から5番目の文字を結合して置換文字列を更新する(ステップST75)。
ここでは、相違単語“S11Aフラグ”、“S12Aフラグ”および“S13Aフラグ”の先頭から5番目の文字は“フ”である。また、相違単語“S11A名前”、“S12A名前”および“S13A名前”の先頭から5番目の文字は“名”である。したがって、相違単語“S11Aフラグ”の置換文字列は“S11Aフ”である。相違単語“S12Aフラグ”の置換文字列は“S12Aフ”である。相違単語“S13Aフラグ”の置換文字列は“S13Aフ”である。相違単語“S11A名前”の置換文字列は“S11A名”である。相違単語“S12A名前”の置換文字列は“S12A名”である。置換文字列“S13A名前”の置換文字列は“S13A名”である。
各置換文字列をパラメータ化した場合、“S11Aフ”、“S12Aフ”および“S13Aフ”で1つ目のパラメータ、“S11A名”、“S12A名”および“S13A名”で2つ目のパラメータを用意することになるので、パラメータ数は“2”である。パラメータ数“2”は、ステップST74におけるパラメータ数“1”よりも多い。
このため、置換文字列決定部150は、ステップST75で特定した置換文字列について1文字分の拡大を元に戻す。すなわち、置換文字列決定部150は、ステップST74で特定した置換文字列“S11A”、“S12A”および“S13A”をパラメータ化対象の置換文字列として確定する。置換文字列決定部150は、当該置換文字列に関するパラメータ化情報116(パラメータ化情報116のレコードと称してもよい)を生成し、記憶部110に格納する。
図49は、パラメータ化情報の例(その4)を示す図である。パラメータ化情報116cは、図48の処理に応じて置換文字列決定部150により生成されるパラメータ化情報を例示している。パラメータ化情報116cは、コードクローン情報CL6に対して、パラメータ数“1”、コードC61(第1コード)に対する置換文字列“S11A”、コードC62(第2コード)に対する置換文字列“S12A”、コードC63(第3コード)に対する置換文字列“S13A”という情報を含む。
このように、置換文字列決定部150は、3以上のソースコードが指定された場合にも、当該ソースコードからコードクローンを検出し、当該コードクローンに対して、可読性および再利用可能性の高い共通化を行える。
ところで、図4,5の例では、コードクローン共通化の単純な方法の例として、コードC11,C12間、または、コードC21,C22間で相違する箇所(相違する文字)のみをパラメータ化することを例示した。以下では、サーバ100によるパラメータ化方法の比較例として、コードクローン共通化の単純な処理の具体例を補足する。
図50は、コードクローン共通化の単純な処理の例(比較例)を示す図である。例えば、コードC71,C72は、2つの異なるソースコードが抽出されたコードクローンである。コンピュータを用いてコードC71,C72を比較し、コードC71,C72の共通の箇所に記述され互いに異なる単語を抽出する。テーブルT3は、当該比較に応じてコードC71およびコードC72から抽出された各単語を例示している。この場合、テーブルT3の同一レコードに属する各単語を比較することで、単語間の相違を得ることができる。例えば、テーブルT3の最上部のレコードにはコードC71から抽出した相違単語“納品−フラグ”が登録され、コードC72から抽出した相違単語“発送−フラグ”が登録されている。両相違単語間の文字の相違は、“納”と“発”との相違、および、“品”と“送”との相違である。テーブルT3では、連続する相違文字を繋げて、当該相違を“納品<=>発送”と表記している。こうして、コンピュータにより相違する文字を抽出し、相違ごとにパラメータ化して、コードC71,C72を共通コード化することもできる。この場合、例えば、テーブルT3の例では、“納品”および“発送”の相違に対して1つ目のパラメータを用意し、“11”および“22”の相違に対して2つ目のパラメータを用意することが考えられ、合計2つのパラメータを用意することになる。
しかし、このように相違箇所だけをパラメータ化する方法を、実際のソースコードに適用すると、図4,5で例示したように、可読性や再利用可能性の低い共通コードが作成されてしまうおそれがある。
これに対し、サーバ100では、各コードクローンにおける相違単語のうち、互いに相違する文字位置から前方または後方に1文字以上拡大した意味のある文字列範囲を、パラメータ化対象の置換文字列とする。これにより、単に相違箇所のみをパラメータ化するよりも、共通コードの可読性、および、再利用可能性を高めることができる。
例えば、上記のように、サーバ100は、パラメータ化候補の文字列範囲を1文字ずつ拡大しながらパラメータ数の増減を確認し、パラメータ数が少なくなる置換文字列を優先的に選択する。すると、変数名や処理名(例えば、関数名、オブジェクト名、サブルーチン名)などに含まれる複数の単語について意味のある文字列の単位でプレースホルダを設定できる(例えば、プレースホルダを“?”として、変数名を“?フラグ”とするなど)。これにより、ユーザは、パラメータ化された部分について、変数名や処理名などのパラメータの意味を比較的容易に把握可能となる。すなわち、置換文字列の可読性を高められる。また、パラメータ数を少なくすることで、ある程度まとまった文字列範囲をパラメータ化でき、共通コードの再利用可能性を高められる。例えば、パラメータ部分(プレースホルダ部分)に挿入可能な文字列の自由度が増し、共通コードの再利用可能性が高まる。特に、この場合でも、共通処理内で使用される変数の種類について、例えば、“?フラグ”の“フラグ”という意味のある部分を共通化し、その前方部分をパラメータ化できる。このため、ユーザは、当該個所に設定される変数が“フラグ”であることを意識しながら、パラメータ化した箇所に、意味のある単位で任意の文字列を設定できる。
このように、パラメータ化情報を生成することで、サーバ100は、共通コードの可読性、および、再利用可能性を高め、ユーザによるプログラムの作成や保守に伴う作業を省力化できる。こうして、サーバ100は、ソフトウェア開発の効率を改善することができる。
なお、第1の実施の形態の情報処理は、演算部1bにプログラムを実行させることで実現できる。また、第2の実施の形態の情報処理は、プロセッサ101にプログラムを実行させることで実現できる。プログラムは、コンピュータ読み取り可能な記録媒体13に記録できる。
例えば、プログラムを記録した記録媒体13を配布することで、プログラムを流通させることができる。また、プログラムを他のコンピュータに格納しておき、ネットワーク経由でプログラムを配布してもよい。コンピュータは、例えば、記録媒体13に記録されたプログラムまたは他のコンピュータから受信したプログラムを、RAM102やHDD103などの記憶装置に格納し(インストールし)、当該記憶装置からプログラムを読み込んで実行してもよい。
以上の第1,第2の実施の形態を含む実施形態に関し、更に以下の付記を開示する。
(付記1) コンピュータが、
互いに類似する複数のコードそれぞれにおいて共通の箇所に記述され互いに相違する複数の単語を抽出し、前記複数の単語の間で相違する相違文字の位置を検出し、
前記複数の単語それぞれのうち、前記位置の前方に連なる1以上の文字および前記位置の後方に連なる1以上の文字の両方または何れか一方と前記相違文字とを含む文字列を、パラメータ化の対象部分とする置換文字列と決定し、
前記複数のコードそれぞれの前記置換文字列の情報を出力する、
パラメータ化方法。
(付記2) 前記決定では、前記複数のコードと前記置換文字列の候補とを用いて作成される共通コードに含まれるパラメータの数に基づいて、前記置換文字列を決定する、付記1記載のパラメータ化方法。
(付記3) 前記決定では、前記置換文字列の複数の候補のうち前記複数の候補それぞれに応じた共通コードに含まれる前記パラメータの数が少ない候補を優先的に選択することで、前記置換文字列を決定する、付記2記載のパラメータ化方法。
(付記4) 前記決定では、前記位置を起点に1文字ずつ前記置換文字列の候補に対応する文字列範囲を拡大し、1文字拡大するたびに前記パラメータの数を計算し、今回の前記パラメータの数が前回の前記パラメータの数よりも増えると、前回の前記文字列範囲を前記置換文字列と決定する、付記3記載のパラメータ化方法。
(付記5) 前記決定では、更に、前記複数の単語それぞれに含まれる所定の文字または隣接する文字の種類の変化に応じて前記置換文字列を決定する、付記2乃至4の何れか1項に記載のパラメータ化方法。
(付記6) 前記決定では、更に、辞書情報に登録された所定単語を前記複数の単語に含まれる文字列の中から特定し、前記複数の単語のうち前記所定単語以外の部分から前記置換文字列を決定する、付記2乃至5の何れか1項に記載のパラメータ化方法。
(付記7) 前記複数のコード、および、前記複数のコードそれぞれの前記置換文字列の情報に基づいて、各コードの前記置換文字列をパラメータに置換した共通コードを出力する、付記1乃至6の何れか1項に記載のパラメータ化方法。
(付記8) 前記複数のコードは、複数のソースコードの比較に応じて検出されたコードクローンである、付記1乃至7の何れか1項に記載のパラメータ化方法。
(付記9) 互いに類似する複数のコードを記憶する記憶部と、
前記複数のコードそれぞれにおいて共通の箇所に記述され互いに相違する複数の単語を抽出し、前記複数の単語の間で相違する相違文字の位置を検出し、前記複数の単語それぞれのうち、前記位置の前方に連なる1以上の文字および前記位置の後方に連なる1以上の文字の両方または何れか一方と前記相違文字とを含む文字列を、パラメータ化の対象部分とする置換文字列と決定し、前記複数のコードそれぞれの前記置換文字列の情報を出力する演算部と、
を有する情報処理装置。
(付記10) コンピュータに、
互いに類似する複数のコードそれぞれにおいて共通の箇所に記述され互いに相違する複数の単語を抽出し、前記複数の単語の間で相違する相違文字の位置を検出し、
前記複数の単語それぞれのうち、前記位置の前方に連なる1以上の文字および前記位置の後方に連なる1以上の文字の両方または何れか一方と前記相違文字とを含む文字列を、パラメータ化の対象部分とする置換文字列と決定し、
前記複数のコードそれぞれの前記置換文字列の情報を出力する、
処理を実行させるパラメータ化プログラム。