EN JP CN

Klocwork Refactoring

Klocwork Refactoring

Klocwork Refactoring

Klocwork Refactoring

リファクタリングは、プログラムの動作を変更しないでコードを簡略化および明確化するためのプロセスです。最初と最後の生成物は、機能的に同じです。リファクタリングにより、コードは次のようになります。

  • 維持および再利用がしやすくなる
  • 理解しやすくなる
  • 変更コストが抑えられる

コーディング環境での Klocwork Refactoring の使用

ほとんどのリファクタリングオプションの場合、最初にリファクタリングするコードをいくつか選択する必要があります。次に右クリックして [Klocwork] メニューを選択し、適切なリファクタリングオプションを選択します。キーボードのショートカットを使用することもできます。ショートカットについては、以下を参照してください。

Vim の場合、KlocworkDesktop Analysis パッケージではプラグインが自動的にインストールされません。設定するには、以下を参照してください。

使用可能なリファクタリング

以下の操作ができます。

  • エンティティの名前の変更 範囲はファイルローカルです。 識別子名をわかりやすいものにします。
  • メソッドまたは関数の抽出 (Eclipse および Visual Studio での重複検出) 小さく論理的な関数を作成するために、大きく不便な関数から抽出します。新たに抽出された関数はソースファイルに追加され、選択したコードはその関数の呼び出しに置換されます。
  • 変数の導入 (Eclipse および Visual Studio での重複検出) 複雑な式を簡略化します。式の出現は新しい変数に置換されます。
  • インライン変数 与えられた変数のすべての出現を初期値に置換します。 これは、変数の導入の逆です。
  • インライン関数 過度にセグメント化されたソースレイアウトのオーバーヘッドを削除します。インラインの典型的な候補は、少ないいくつかの場所から呼び出される単関数ですが、内部ループからの呼び出しなど、実行時に頻繁に呼び出されることもあります。これらは、関数呼び出しのオーバーヘッドの削除により最高の利点が得られることのある関数です。インライン関数には、メソッドのボディの呼び出し側のボディへの配置、およびメソッドの削除が含まれます。
  • ヘッダーの解析 欠落した推移的 include および不要な include を報告します。
  • ヘッダーの最適化 使用していないヘッダーおよび欠落した推移的ヘッダーの変更を、ユーザーの確認なしにすべて 1 つのステップで適用します。

名前の変更

識別子名をわかりやすいものにするために、変数または関数の名前を変更します。デモを見るには。以下の名前を変更できます。

  • ローカル変数
  • 関数パラメーター
  • static 関数および変数

既存の変数、関数、タイプ、または名前空間の非表示や、名前の競合を回避するために、新しい名前は、既存のコードに対してチェックされます。

int boo(int b) { 
}
int bar(int (*func)(char*)) { 		 
    return 1; 
} 
void foo(int a) { 
    int i = 2;
    i = 3;
    a = 567;
    a = boo(a); 
}

上の抜粋で、bfunca および i は、すべて指定したとおりに名前を変更できます。

抽出関数

抽出関数オプションを使用すると、新しい関数が作成され、選択したコードはその関数のボディとして挿入されます。選択したコードは、完全なステートメントおよび/または式の、構文的に完全で空のないシーケンスであることが必要です。

実装に関する注意事項

  • 選択したコードフラグメントは、新しい関数の呼び出しに置換されます。コードフラグメント内で使用されている変数があれば、入力または出力のパラメーターとして新しい関数に渡されます。
  • プリミティブ型 (pointer、char、bool、int など) の 1 つの出力パラメーターのみを持つ新しい関数は自動的に 1 つの関数に変換され、この型の値を返します。出力パラメーターは返されません。
  • C 出力の場合、パラメーターは元の型のポインターとして宣言されます。
  • C++ 出力の場合、パラメーターは元の型のリファレンスとして宣言されます。現在の関数が C++ クラスのメンバー関数である場合、新しい関数の宣言が、保護されているメンバーとしてクラス定義に挿入されます。
  • 元のインデントおよび空白は、可能な限り保存されます。
  • 選択内のコメント、マクロ、およびプリプロセッサディレクティブは、コード変換中に保存されます。次のコードの例は、リファクタリング用に選択されたコードを示します。
int foo() {
  int a;
  /* selection starts -> */
  #define MY_MACRO 1
  a = MY_MACRO;
  /*<- selection ends*/
  a = a + 20;
  return a;
}

抽出された関数に 'define' ディレクティブが保存されることがわかります。

int extracted_function()
{
  int a;
  #define MY_MACRO 1
  a = MY_MACRO;
  return a;
}

制限事項

  • 選択したコードフラグメントにジャンプステートメント ("goto") を含めることはできませんが、return ステートメントは機能します。
  • 選択したコードフラグメントにラベルステートメントを含めることはできませんが、(ラベル付きの) switch ステートメントは機能します。
  • テンプレート関数からの抽出はサポートされません。

int main() {		 
 int a;			       
   a++ ;			
  return a;
}

フィールド'a++' を 'new_function' に抽出できます。

結果

 void new_function(int *a) {  
  (*a)++ ; 
}
int main() { 
 int a; 
 new_function(&a) ; 
 return a; 
}


変数の導入

変数の導入では、選択した式から新しいローカル変数を簡単に作成し、そのローカル変数を式で初期化し、コード内のすべての式の出現を新しく導入された変数の参照で置換します。反対のアクションは、変数を初期の式で置換する、変数のインラインによるリファクタリングです。

実装に関する注意事項

  • 選択した式で初期化された、新しいローカル変数の宣言は、現在のステートメントに挿入されます。選択した式は、新しい変数の名前に置換されます。
  • 既存の変数、関数、タイプ、または名前空間の非表示や、名前の競合を回避するために、新しい名前は、既存のコードに対してチェックされます。
  • C++ の場合、新しい変数の宣言および初期化子は、1 つのステートメントに統合され、選択したステートメントの前に直接挿入されます。
  • C の場合、宣言および初期化子を分割する必要があることがあります。宣言は、現在のブロックまたは関数の最初に挿入され、割り当ての初期化は、選択したステートメントの前に直接挿入されます。

下の抜粋の太字テキストは、変数に置換できます。

int main() { 				
    int c; 				     
    c = 1 +  2 + 3 + 4 + 5 ;		     
    return c; 				      
}

結果

int main() { 
  int temp ; 
 int c;
  temp = 2 + 3 + 4 + 5 ; 
 c = 1 +  temp ;				     				  
 return c; 
}

インライン変数

インライン変数では、与えられた変数のすべての出現を初期値に置換します。反対のアクションは、変数の導入によるリファクタリングです。

太字の変数は、式で置換できます。

int main() { 
  int temp ; 
 int c;
  temp  = 2 + 3 + 4 + 5; 
 c = 1 +  temp ;				     				  
 return c; 
}

結果

int main() { 				
    int c; 				     
    c = 1 +  2 + 3 + 4 + 5 ;		     
    return c; 				      
}

インライン関数

関数をインラインすると、関数の完全なボディが、選択した関数の出現ごとに挿入されます。

この機能に関するデモを見るにはここをクリックします

実装に関する注意事項

  • 関数の定義を選択すると、関数がソースファイルから削除され、この関数の各呼び出しは、関数のボディに置換されます。
  • 関数の呼び出しを選択すると、この呼び出しのみがインラインされ、関数定義は変更されません。
  • 関数のパラメーターおよびローカル変数は、置換時に名前が変更されます。

制限事項

  • サポートされるのはインライン関数および static 関数のみです。
  • 次のものはインラインできません。
    • 再帰関数
    • 複数の return ステートメントを持つ関数
    • アドレスにより参照される関数

static int foo(int a) {			  
    int b = a + 2;				    
    return b;				      
}						  
int main() {				      
    int c;					     
    c =  foo(1) ;				 
    return c; 
} 

この例では、'foo' をインラインできません。

結果

int main() { 
 int c;
  int a = 1;  
  int b = a + 2;  
  c = b; 
 return c;
}

システムヘッダーで宣言された関数はインラインできない

システムヘッダーで関数定義が検出された場合、次のようなメッセージが表示されます。

たとえば、このメッセージは、下の抜粋の 'math.h' から 'pow' をインラインしようとすると、表示されます。

#include <iostream>
 #include <stdio.h>
 #include <math.h>
 
 using namespace std;
 
 #define PI 3.14
 
 static float getArea(float radius) {
   float area = PI * *pow(radius, 2)*;
   return area;
 }

関数をインラインできません:この関数は、その完全修飾名で呼び出されます

別のクラスメンバーから直接呼び出される関数はインラインできますが、次のような状況で 'x->foo()'、'x.foo()' などの関数をインラインしようとすると、このメッセージが表示されます。

 class A{
    void foo() {...}
    void abc();
 }
 void A::abc()
 {
    foo(); //we can inline this
 
    A::foo(); //we can't inline this
    A x = new A();
    x->foo(); //we can't inline this
 }

ヘッダー解析

ヘッダーの解析および最適化に関するデモを見てください (ここをクリックします)。

ヘッダー解析機能を使用すると、コードのインクルード構造に関する問題を解決することができます。インクルード構造があると、コンパイル時間が長引き、システムの維持が難しくなることがあります。

これらの問題は、次の 2 つの Klocwork Refactoring により解決できます。

ヘッダーの解析

ヘッダーの解析は、不要な、または欠落した推移的 include を検出し、リファクタリング候補を表示します。

このリファクタリングオプションの機能は、IDE の選択に基づきます。

ヘッダーの解析は、Vim では使用できません。

ヘッダーの最適化

[ヘッダーの解析] リファクタリングオプションを使用すると、プロンプト表示なしに、不要な、または欠落した include を 1 つのステップで検出し、リファクタリングします。これは、不要な、または欠落した推移的 をユーザーに通知し、リファクタリング候補と実装の可否を表示する、ヘッダーの解析とやや対照的です。

Visual Studio および Eclipse の場合、現在のファイル内の任意の場所を右クリックし、[Klocwork] > [ヘッダーの最適化] をクリックします。(ヘッダーを最適化するためにコードを選択する必要はありません)。

Visual Studio でのヘッダー解析

ヘッダー解析機能を使用すると、コードのインクルード構造に関する問題を解決することができます。インクルード構造があると、コンパイル時間が長引き、システムの維持が難しくなることがあります。

Visual Studio では、不要なまたは欠落した推移的 include が次の 1 つとして指摘リストに報告されます。HA.DUPLICATEHA.OPTIMIZE または HA.UNUSED

注意: ヘッダー解析指摘にはマーカーはありません。

  1. ヘッダー解析指摘を手動で解決するには、指摘リストで指摘をダブルクリックします。すると、当該指摘を含むコード行が表示されます。
  2. 指摘マーカーを右クリックすると、次のようなアクションがあるポップアップメニューが表示されます。

変更すると、当該指摘が指摘リストから消えます。

これらの変更を自動的に行わせるには、現在のファイル内の任意の場所を右クリックし、[Klocwork] > [ヘッダーの最適化] をクリックします。 これにより、現在のファイル内のヘッダー指摘がすべて自動的に修正されます。

これらの指摘が指摘リストに表示されないようにするには、ヘッダー解析チェッカーを無効にします。

Visulal Studio で未使用関数を削除

Visulal Studio プラグインの 1 つを使用する場合は、コードを迅速にリファクタリングして未使用関数を削除することができます。

定義済みでも未使用の関数は、類似した名前の誤った関数が呼び出されるなど、開発において混乱を招く可能性があります。まれに、使用されない関数が最終的な実行可能ファイルに挿入され、その他の脆弱性をもたらす可能性もあります。Klocwork は未使用の関数を特定する 2 つの方法を備えています。

  1. このような問題の 1 つを修正するには、エディターの左余白の指摘マーカーを右クリックし、次のアクションから 1 つを選択します。
    • UNUSED.FUNC.WARN には、この関数を静的にしますを選択します。
  2. UNUSED.FUNC.GEN には、未使用関数を削除しますを選択します。

Visual Studio でのショートカットのリファクタリング

Klocwork Refactoring の各種オプションには、次のショートカットからアクセスすることができます。

リファクタリング ショートカット
抽出関数Alt+r、e
インライン関数Alt+r、f
インライン変数Alt+r、i
変数の導入Alt+r、v
ヘッダーの最適化Alt+r、o
名前の変更Alt+r、r

Eclipse でのヘッダー解析

Eclipse では、現在のファイル内の任意の場所を右クリックし、[Klocwork] > [ヘッダーの解析] または [ヘッダーの最適化] を選択すると、[ヘッダーの解析] および [ヘッダーの最適化] のリファクタリングオプションの使用により、ヘッダー指摘を修正できます。

[ヘッダーの解析] メニューオプションおよび [ヘッダーの最適化] メニューオプションは、ヘッダー解析チェッカーにより制御されます。これらのチェッカーを無効にする場合、ヘッダー解析リファクタリングを使用できません。

[ヘッダーの解析] リファクタリングオプションを使用する場合、リファクタリング候補を表示する Quick Fix ポップアップをアクティブにするマーカーにより、不要な、または欠落した推移的 include が現在のファイルで識別されます。

  1. 現在のファイル内の任意の場所を右クリックし、[Klocwork] > [ヘッダーの解析] をクリックします。(ヘッダーを解析するためにコードを選択する必要はありません)。
  2. バグマーカーをクリックするか、ヘッダーファイルをスクロールして Quick Fixアイコン:
  3. をクリックするか、<Ctrl+1> を使用して Quick Fix ポップアップをアクティブにします。
  4. ポップアップをクリックし、リファクタリングに進みます。

[ヘッダーの最適化] のリファクタリングオプションを使用する場合、ファイルの個別マーカーにアクセスして修正することなく、すべての修正が実行されます。

Eclipse でのショートカットのリファクタリング

Klocwork Refactoring の各種オプションには、次のショートカットからアクセスすることができます。

リファクタリング ショートカット
ヘッダーの解析 Alt+Shift+K、A
抽出関数 Alt+Shift+K、E
インライン関数 Alt+Shift+K、I
インライン変数 Alt+Shift+K、N
変数の導入 Alt+Shift+K、V
ヘッダーの最適化 Alt+Shift+K、O
名前の変更 Alt+Shift+K、R