メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

Polyspace チェッカーを使用してソフトウェアの複雑度を低減する

ソフトウェアの複雑度とは、ソフトウェア モジュールまたはソース ファイルの、定量化が可能なメトリクスのことです。種類はさまざまで、行数、パス数、関数の数、関数呼び出しツリーの複雑度などがあります。このようなメトリクスがしきい値を超えると、Polyspace® ソフトウェア複雑度チェッカーが起動します。ソフトウェアの複雑度が高いことは、コードの読み取り、理解、デバッグが難しいことを示している可能性があります。複雑なプロジェクトを後からリファクタリングするのではなく、ソフトウェアの複雑度を開発中に許容可能なレベルに維持するほうが効率的です。ソフトウェア複雑度チェッカーを使用して、複雑なモジュールを開発サイクルの早期に検出することにより、後で行うリファクタリングの手間を減らしましょう。

すべてのファイルと関数に対してコード複雑度メトリクスの絶対値を計算することもできます。Polyspace を使用したコード複雑度メトリクスの計算を参照してください。

Hersteller Initiative Software 標準を使用したコード複雑度のチェック

コードのコード複雑度メトリクスが指定されているしきい値を超えると、ガイドラインのコーディング ルールが違反を報告します。既定では、Polyspace Bug Finder™ はしきい値を、Hersteller Initiative Software (HIS) コード複雑度標準によって指定されている値に設定します。コード複雑度メトリクスが HIS 標準で規定されている範囲内にあるかどうかを確認するには、[チェッカーの選択] ウィンドウを使用してガイドラインのコーディング ルールを有効にします。

HIS 標準に照らしてチェックする場合、ガイドライン チェックの既定のしきい値を変更する必要はありません。

カスタムしきい値を使用したコード複雑度のチェック

コードのカスタム コード複雑度しきい値を定義できます。最初に、自分のユース ケースのベスト プラクティスに応じて、しきい値の適切なセットを決定します。たとえば、新しいプロジェクトまたは新しく開発するコードを解析するときに、[goto ステートメントの数がしきい値を超えている] のしきい値をゼロに設定して、GOTO ステートメントの使用を減らすことができます。レガシ ライブラリを含むモジュールを解析するときには、しきい値を高い数値に設定するのが良い場合もあります。

しきい値のセットを定義したら、[チェッカーの選択] ウィンドウでこれらのしきい値を指定できます。

  • [チェッカーの選択] ウィンドウを開きます。このウィンドウを開く方法は、ご使用の Polyspace 製品によって異なります。

  • [ガイドライン][ソフトウェアの複雑度] に移動して、使用するルールを有効にします。

  • [しきい値] フィールドでカスタムしきい値を指定します。

ソフトウェアの複雑度の特定と低減

Bug Finder 解析を実行することによるソフトウェアの複雑度の特定

ソフトウェアの複雑度を特定するには、チェッカーのしきい値を構成します。たとえば、次の表に示されているチェッカーのしきい値を設定します。

しきい値は、ソフトウェアの複雑度の許容レベルを示します。複雑度を高める可能性があるコード内の問題を特定するには、ソフトウェア複雑度チェッカーを構成してから、Polyspace Bug Finder 解析を実行します。次のコードについて考えます。

 long long power(double x, int n){
	 long long BN = 1;
	 for(int i = 0; i<n;++i){
		 BN*=x;
	 }
	 return BN;
 }
 
 double AppxIndex(double m, double f){//Noncompliant
	 double U = (power(m,2) - 1)/(power(m,2)+2);
	 double V = (power(m,4) + 27*power(m,2)+38)/(2*power(m,2)+3);
	 return (1+2*f*power(U,2)*(1+power(m,2)*U*V+ power(m,3)
	         /power(m,3)*(U-V)))/( (1-2*f*power(U,2)*(1+power(m,2)*U*V 
	        + power(m,3)/power(m,3)*(U-V))));
 }
関数 AppxIndex が複雑度を高くしているように思われます。複雑度を低減する方法ははっきりしません。ソフトウェア複雑度チェッカーが複雑度の原因の特定に役立ちます。

Bug Finder 解析の後で、構成されたチェッカーが以下のように起動します。

これらのチェッカーは、関数 AppxIndex がコードの読み取り、理解、デバッグを難しくしている可能性を示しています。コードの複雑度を低減するために、報告されたチェックに対処します。

ソフトウェアの複雑度を低減する

特定された問題に対処することにより、コードの複雑度を低減します。この場合、報告されたチェックの根本原因は、関数 AppxIndex が 1 つのタスクを実行するのではなく、複数のタスクを実行していることです。たとえば、この関数は最初に U、その後 V を計算し、最後に UV の両方を含む非常に長い式を評価します。この問題を解決するには、関数 AppxIndex をリファクタリングして、各タスクを別個の関数にデリゲートします。長い式は細かく分解できる場合があります。次に例を示します。

// This code calculates effective index of materials  as described in
// the formula in 10.1364...
// power(x,n) returns the nth power of x (x^n)
// n is an integer
// x is a double
// return type is long long

long long power(double x, int n){//Compliant
	long long BN = 1;
	for(int i = 0; i<n;++i){
		BN*=x;
	}
	return BN;
}
// CalculateU(m) calculates the first intermediate variable
// required to calculate  polarization
// m is the relative refractive index
// return type is double;

double CalculateU(double m){//Compliant
	return (power(m,2) - 1)/(power(m,2)+2);
}
// CalculateV(m) calculates the second intermediate variable
// required to calculate  polarization
// m is the relative refractive index
// return type is double;

double CalculateV(double m){//Compliant
	return (power(m,4) + 27*power(m,2)+38)/(2*power(m,2)+3);
}
// CalculateMid(m,f) calculates the large term present 
// in both numerator and denominator
// of the effective index calculation
// m is the relative refractive index
// f is the fillfactor 
// return type is double;

double CalculateMid(double m, double f){//Compliant
	double U = CalculateU(m);
	double V = CalculateU(m); 
	return 2*f*power(U,2)*(1+power(m,2)*U*V + power(m,3)/power(m,3)*(U-V));
}
//AppxIndex(m,f) calculates the approximate effective index
// m is the relative refractive index
// f is the fillfactor
//return type is double
double AppxIndex(double m, double f){//Compliant
	return (1+CalculateMid(m,f))/( (1-CalculateMid(m,f)));
}
このコードでは、ソフトウェア複雑度チェッカーは 1 つも起動しません。これは、このコードの複雑度が許容可能なレベルに低減されたことを示します。ソフトウェアの複雑度を低減するには、以下を行います。

  1. コードに十分な数のコメントを付けてドキュメント化します。

  2. AppxIndex が実行する大きく複雑なタスクを小さくて簡単なタスクに分割し、CalculateUCalculateVCalculateMid などの個別の関数にデリゲートします。これで、関数 power の呼び出し頻度が少なくなりました。べき乗を計算する別の関数を後で実装し、現在の関数ではなく新しい関数を使用する場合、行わなければならない置き換えは少なくなります。

  3. 1 つの特定のタスクを実行し、できるだけ機能のオーバーラップが少ない新しい関数を記述します。その結果、これらの関数に含まれる同じオペランドの繰り返しは少なくなります。

ソフトウェア複雑度チェックへの対処の詳細については、チェッカーのドキュメントを参照してください。

コードのリファクタリングができない場合、報告されたチェックにコード注釈で対処します。たとえば、複雑なライブラリを使用している場合、ライブラリで報告されるチェックに注釈を付けることができます。コードへの注釈付けと既知の結果または許容可能な結果の非表示を参照してください。ファイルまたは関数コード メトリクスに注釈を付けると、対応するソフトウェア複雑度チェッカーにも同じコメントで注釈が付けられます。

参考

トピック