印刷用ページ       送信     
クリックして評価とフィードバックをお寄せください
MSDN
MSDN ライブラリ
テクニカルドキュメント
Visual Studio 2005
Visual C# 2005
 Visual Studio 2005 を使用した C# コードのリファ...
Visual Studio 2005 を使用した C# コードのリファクタリング

Andrew W. Troelsen
Intertech Training Non-MS link

July 2004
日本語版最終更新日 2004 年 8 月 3 日

適用対象 :
   Microsoft Visual Studio 2005
   Microsoft Visual C#.NET 2.0

概要 : この記事では、コードのリファクタリングの役割、および Visual Studio 2005 によってサポートされるリファクタリングの手法について説明します。

目次

リファクタリング プロセスの定義
Visual Studio 2005 でのリファクタリングのサポート
メソッドの抽出
フィールドのカプセル化
インターフェイスの抽出
パラメータの再順序付け
パラメータの削除
名前の変更
ローカル変数のパラメータへの昇格
メソッド スタブの生成
まとめ

メモ   この記事は、読者が C# プログラミング言語と .NET プラットフォームについての知識を持っていることを前提にしています。 以下のページを理解する上で、以前リファクタリングした経験は役立ちますが必須ではありません。

リファクタリング プロセスの定義

すべてのエンジニアの 1 日のほとんどは、既存のコードを再処理して、何らかの意味で "より良い" ものにすることに費やされると言っても過言ではないでしょう。 多くの場合、"より良いコード" は主観的な用語ですが、いくつかの一般的な機能向上としては、 オブジェクト指向の推奨される方法の準拠、型の安全性の増大、パフォーマンスの向上、コードの読みやすさと保守性の向上などが含まれます。

リファクタリングとは、プログラムの意図する機能を保持したまま実際に "より良い" ものになるように、既存のコードを変更するために使用される、形式的で機械的なプロセスです。 プログラムの全体のデザインの向上に加え、リファクタリング プロセスによって、長期的に見て大幅に保守および拡張しやすくなるコードが作成される傾向があります。

多くの場合、リファクタリングはプログラミング上の常識のわかりきった (ほとんど単純すぎる) 作業のように見えます。 たとえば、[Replace Magic Number with Symbolic Constant] (マジック ナンバーをシンボル定数に置換する) リファクタリングとは、アプリケーションが明確に理解されている値を持つ場合に、値を 1 字ずつ (つまり、マジック ナンバーを) 入力するのではなく、名前付きの定数を作成することを示します。 たとえば、次の型について考えます。

class SimpleMath
{
  public static double CalcCircumference(double diameter)
  { return 3.14 * diameter; }
}

[Replace Magic Number with Symbolic Constant] を使用してリファクタリングできます。

class SimpleMath
{
  public const double PI = 3.14;
  public static double CalcCircumference (double diameter)
  { return PI * diameter; }
}

次の場合は、この変更が機能向上につながるということに同意いただけるでしょう。

  • コードが読みやすくなった場合 ("PI" (π) の意味は値 3.14 より明確です)
  • このシンボル定数の値を変更する必要がある場合 (PI をより高い精度で使用する場合など) は、(マジック ナンバーをそれぞれ変更するのではなく) 定数の宣言を変更するだけで済みます。

その他のリファクタリングは、あまり単純すぎたり、わかりきったものではありません。 たとえば、[Tease Apart Inheritance] リファクタリングは、1 つの既存のクラス階層の形を複数の (関連付けられた) 階層に大幅に変更するために適用できます。 この単一のリファクタリングは、通常、[Extract Class]、[Move Method]、[Move Field]、[Pull Up Method]、[Pull Up Field] など、関連付けられた複数のリファクタリングを使用することを示します。

再度、リファクタリングによって形式的で機械的なプロセスがプロセスに (冗長性は許容しながら) 適用される場合、それらのタスクの確実なロードマップが手元にできあがります。

リファクタリングの由来

前の段落で、一般的なリファクタリングの一部 ([Move Method]、[Move Field] など) について述べました。 リファクタリングの面白いところは、実際には確定している普遍的なやり方というものがないということです。 たとえば、"マジック ナンバーをシンボル定数に置換する" という方法は、単に簡単に "マジック ナンバーが不適切...Const または Enum を使用" と呼ばれる可能性もあります。

ただし、プログラミング コミュニティ全体としては、既知であり、時間の経過した一連のリファクタリング手法を使用することに合意している傾向があります。 これらの認識されているリファクタリング手法の多くが、Martin Fowler 著『Refactoring: Improving the Design of Existing Code』 (Addison Wesley、1999 年) に記載されています。 リファクタリング プロセスを行ったことがない場合は、このテキストのコピーを参照するか、最低でもサポート用のその後の情報を得るための ウェブサイト (英語) Non-MS link を参照することをお勧めします。

Visual Studio 2005 でのリファクタリング サポート

以前の非効率的な時代は、通常、リファクタリングには膨大な手動の作業が必要でした。 開発者が変更対象のコードを識別すると、コピー、貼り付け、検索、置換、コンパイル、テスト (繰り返し) の各手法を大量に使用する傾向がありました。 これは控えめに言っても、時間がかかりエラーが発生しやすい方法でした。

幸運なことに、Visual Studio 2005 では、リファクタリング プロセスを自動化する処理が多量に行われます。 [Refactoring] メニュー、関連付けられたショートカット キー、SmartTags、およびコンテキスト依存のマウスの右クリック、またはこれらのいずれかを使用して、コードの形体を最小限の労力で大幅に変更できます。 表 1 では、Visual Studio 2005 によって認識される一般的なリファクタリングの一部が定義されています。

表 1. Visual Studio 2005 リファクタリング

リファクタリング手法実際の意味
[Extract Method]コード ステートメントの選択に基づいて新しいメソッドを定義できます。
[Encapsulate Field]パブリック フィールドを .NET プロパティによってカプセル化されたプライベート フィールドにします。
[Extract Interface]既存の型メンバのセットに基づいて新しいインターフェイス型を定義します。
[Reorder Parameters]メンバ引数の再順序付けの方法を提供します。
[Remove Parameters]手法名から予想できるように、このリファクタリングは、パラメータの現在のリストから指定した引数を削除します。
[Rename]プロジェクト全体のコード トークンの名前 (メソッド名、フィールド、ローカル変数など) を変更できます。
[Promote Local Variable to Parameter]ローカル変数を定義メソッドのパラメータ セットに移動します。

これらのリファクタリングがどのように動作するか、詳細に個別に説明していきます。 各例を説明していきますが、その間、ほとんどのリファクタリングが複数の手法 (メニュー システム、コンテキストのクリックなど) を使用してアクティブにすることができるという点に注意してください。 筆者はコンテキスト依存のマウスの右クリックを使用する傾向があります、適切な場合はその他のオプションも指示します。

メソッドの抽出

最初に検証するリファクタリングは、メソッドの抽出です。 読者の皆さんは、余計な処理が多すぎる "気がする" 型メンバを作成したことがあると思います。 おそらく、ユーザー名とパスワードを取得するだけのメソッドを作成し、その結果を後から使用するためにローカル変数に配置したことがあるでしょう。

using System;

namespace RefactoringExamples
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.WriteLine("*** Please enter your credentials ***");
            
      // ユーザー名とパスワードを取得します。
      string userName;
      string passWord;         
      Console.Write("Enter User Name: ");
      userName = Console.ReadLine();
      Console.Write("Enter Password: ");
      passWord = Console.ReadLine();
 
    }
  }
}

この Main() メソッドには特に悪いところはありませんが、Program クラスのその他の部分がユーザーに識別情報を求めるプロンプトを示す必要がある場合、どのような処理が行われるかを考慮します。 これには明らかに大量の冗長な (そのため保守しづらい) コード ステートメントが必要になります。

理論上は、Main() メソッドを、一般的なロジックが (たとえば) GetCredentials() という名前の付いた新しいメソッドにスクレープされるようにリファクタリングすることができます。 このようにして、ユーザー名とパスワードを取得する必要がある Program 型の任意のメンバは、単純に新しいメソッドを呼び出すことができます。 Main() メソッド内のコードは大幅に読みやすくなり、また、その中で関連するステートメントは説明メソッド呼び出しによって置換できます。

GetCredentials() メソッドを手動で作成するのではなく、Visual Studio .NET の [Extract Method] のリファクタリングによって、自動的に新しいメソッドが生成され、選択したコードを後続のメソッド呼び出しと置換されます。 最初に、どのコード ステートメントが新しいメソッドのロジックを表すのかを正確に決定します。 [Extract Method] のリファクタリングに対して設定された次のステートメントを選択したものと想定します (図 1) 。

ms379618.vs2005_refactoring-fig1(ja-jp,VS.80).gif

図 1. [Extract Method] リファクタリングに対するステートメントの選択

この時点で、生成する新しいメソッドの名前を入力できるダイアログ ボックスが表示されます (図 2) 。 コード ステートメントは任意のインスタンス レベルの変数を参照しなかったため、新しいメソッドは自動的にプライベートで静的なものとして定義されることに注意してください (通常、抽出されたメソッドは、可能な限り最も制限的な修飾子が指定されます) 。

ms379618.vs2005_refactoring-fig2(ja-jp,VS.80).gif

図 2. 新しく抽出されたメソッドに対する名前の提供

[OK] をクリックすると、次の更新が表示されます。

namespace RefactoringExamples
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.WriteLine("*** Please enter your name ***");
      GetCredentials();
      Console.ReadLine();
    }
    private static void GetCredentials()
    {
      // ユーザー名とパスワードを取得します。
      string userName;
      string passWord;
      Console.Write("Enter User Name: ");
      userName = Console.ReadLine();
      Console.Write("Enter Password: ");
      passWord = Console.ReadLine();
    }
  }
}

この改訂されたフォームには、3 行しかなく、各行が非常に説明的なので、Main() の処理内容を一目で簡単に確認できます。 読者が GetCredentials() メソッドの背後の詳細を調査する必要がある場合は、自由に行うことができますが、実装ロジックを参照する必要がない場合は、行う必要はありません。

GetCredentials() のこの特別なバージョンは、抽出され、引数をとらないことに注意してください。 この理由は、選択したコードが自己完結型ユニットだったためです。これは、呼び出されたメソッドによって必要とされた変数 (userName および passWord) は、選択にも含まれたことを意味します。 ただし、[Extract Method] リファクタリングに対する次のステートメントの選択のみを行った場合、

Console.Write("Enter User Name: ");
userName = Console.ReadLine();
Console.Write("Enter Password: ");
passWord = Console.ReadLine();

メソッド プロトタイプに、この時点で 2 つの出力パラメータが含まれます (図 3) 。

ms379618.vs2005_refactoring-fig3(ja-jp,VS.80).gif

図 3. Visual Studio 2005 によって抽出されたメソッドは、文脈に応じてプロトタイプ化されます。

結果となる抽出は、次のようになります。

using System;

namespace RefactoringExamples
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.WriteLine("*** Please enter your credentials ***");

      // ユーザー名とパスワードを取得します。
      string userName;
      string passWord;
      GetCredentials(out userName, out passWord);
    }
    private static void GetCredentials(out string userName, 
      out string passWord)
    {
      Console.Write("Enter User Name: ");
      userName = Console.ReadLine();
      Console.Write("Enter Password: ");
      passWord = Console.ReadLine();
    }
  }
}
メモ   選択したステートメントのブロックによって単一の戻り値が発生する場合は、抽出されたメソッドの物理的な戻り値になります。 ただし、選択したステートメントのセットが複数の論理戻り値を必要とする場合は、ステートメントのセットが参照パラメータまたは出力パラメータとして実現されます。

フィールドのカプセル化

すべてのユーザーが (読み込み専用フィールドであったとしても) パブリックにアクセス可能なフィールド データは望ましくないということについて合意しているものと期待されます。 カプセル化の慣習では、.NET プロパティを使用して基盤となる値への安全で管理されたアクセスを実現しながら、型のフィールド データはプライベートとして定義する必要があります。

ただし、引数のために、ユーザー自身よりも経験が薄いエンジニアによって作成された次の構造を継承したものと想定します。

public struct
MyPoint
{
  public int x; 
  public int y; 
  public void SetLocation()
  {

Console.Write("Enter X position: ");
    x = int.Parse(Console.ReadLine());

Console.Write("Enter Y position: ");
    y = int.Parse(Console.ReadLine());
  }
  public void PrintLocation()
  {
    // 新しい場所を印刷します。

Console.WriteLine("[{0}, {1}]", x, y);
  }
}

ここでわかるとおり、MyPoint 型のフィールド データはパブリックとして定義されました。 カプセル化を保存するには、コードを次のようにリファクタリングする必要があります。

  • x フィールドと y フィールドをプライベートとして再定義します。
  • フィールド データの各部分の read / write プロパティを作成します。
  • すべての前のフィールドの割り当てを property set 構文を使用して置換します。
  • すべての前のフィールドのアクセス ロジックを property get 構文を使用して置換します。

また、以前は変更を手動でしか行えなかったのですが、Visual Studio 2005 では [Encapsulate Field] リファクタリングを使用してプロセスが自動化されます。 これを説明するために、x フィールドを選択し、対象となるリファクタリングをアクティブにします (図 4) 。

ms379618.vs2005_refactoring-fig4(ja-jp,VS.80).gif

図 4. [Encapsulate Field] リファクタリングに対するフィールドの選択

[Encapsulate Field] オプションを選択すると、このリファクタリングのスコープの設定を促すプロンプトが表示されます。 図 5 に示すように、推奨されたプロパティ名は Xpos に変更し、[Updated Reference] オプションの [All] 値をオンにします (これによって、選択したフィールドに対するすべての発生値がリファクタリング プロセス中に発生します) 。

ms379618.vs2005_refactoring-fig5(ja-jp,VS.80).gif

図 5. 新しいプロパティの設定

[Preview Reference Changes] チェックボックスをオンにした場合は、提案された変更のすべての結果を記録する最後のダイアログが表示されます (図 6) 。

ms379618.vs2005_refactoring-fig6(ja-jp,VS.80).gif

図 6. 現在のリファクタリングのスコープを表示

この [Encapsulate Field] リファクタリングの最終結果を示します。

public struct
MyPoint
{
  private int x;
  public int XPos
  {
    get{return x;}
    set{x = value;}
  }
  public int y; 
  public void SetLocation()
  {

Console.Write("Enter X position: ");
    XPos = int.Parse(Console.ReadLine());

Console.Write("Enter Y position: ");
    y = int.Parse(Console.ReadLine());
  }
  public void PrintLocation()
  {
    // 新しい場所を印刷します。

Console.WriteLine("[{0}, {1}]", XPos, y);
  }
}

もちろん、同じリファクタリングを残りのパブリック フィールド (y) に適用する場合は、同様の結果が得られます。

インターフェイスの抽出

インターフェイス型の操作に慣れると、可能な場合は、いつでもその便利さを活用せざるを得なくなります。 まとめると、インターフェイスによって、指定された型がサポートできる抽象メンバ (プロパティ、メソッド、およびイベント) のセットが定義されます。 その場合、実装型は適切に見えるように詳細を仕上げます。 インターフェイスの利点は、完全に異なる階層にある複数の型が同じインターフェイスを実装できることを理解すると、わかりやすくなります。 これを踏まえて、インターフェイスによって、階層、名前空間、アセンブリ、および .NET プログラミング言語にわたる多相性を取得できます。

[Extract Interface] リファクタリングによって、既存の型メンバのグループを選択して、新しいインターフェイスの抽象を作成できます。 たとえば、グラフィックス ライブラリを作成しているものと想定します。 最初の型 (TwoDShape) によって次のメンバが定義されます。

// System.Drawing.dll を参照し、
// '使用中' のディレクティブを更新して
// Rectangle 型と Color 型を使用する場合を想定します。
class TwoDShape
{
  public void Draw()
  { /* 関連するコード。 */ }

  public Rectangle GetBoundingRect()
  { /* さらに関連するコード。 */ }

  public Color GetArgb()
  { /* さらにまた関連するコード。 */ }
}

この時点で、ビルドしようとしているその他の型 (たとえば、ThreeDShape および Printer) も Draw()GetBoundingRect()、および GetArgb() という名前の付いたメンバを必要としていることに気付きます。 これらのメンバをカスタム インターフェイス (IRender という名前が付けられる) に抽出すると、インターフェイス ベースの多相性が実現できます。

TwoDShape 型から IRender インターフェイスを抽出するには、3 つのメンバ (それぞれの実装を含む) すべてを選択することによって開始し、[Extract Interface] リファクタリングをアクティブにします。 これを実行すると、インターフェイス名、ファイルの定義、およびインターフェイス メンバ自体を確立できるダイアログ ボックスが表示されます (図 7) 。

ms379618.vs2005_refactoring-fig7(ja-jp,VS.80).gif

図 7. 新しいインターフェイス型の設定

メモ   型メンバのセットを選択するのではなく、単純にクラス (または構造体) の名前強調表示し、[Refactoring] メニューをアクティブにするだけで、インターフェイスを抽出することもできます。 ソース コード ファイル内のさまざまな場所に未定義のインターフェイスのメンバがある場合に、この方法が役立つ可能性があります。

[OK] ボタンをクリックすると、インターフェイス自体を定義する新しいファイルが提供されるだけではありません。

namespace RefactoringExamples
{
  interface IRender
  {
    void Draw();
    System.Drawing.Color GetArbg();
    System.Drawing.Rectangle GetBoundingRect();
  }
}

そのうえ、元のクラス (TwoDShape) が当該のインターフェイスを実装しているのを確認できるのは楽しいでしょう。

class TwoDShape : RefactoringExamples.IRender
{ ... }

この時点で、IRender に対するサポートを使用して、残りのクラスの型 (ThreeDShapePrinter) を定義する準備ができています。 このプロセスを容易にするために、Visual Studio 2005 SmartTags を使用している図 8 について考慮します。

ms379618.vs2005_refactoring-fig8(ja-jp,VS.80).gif

図 8. Visual Studio 2005 SmartTags を使用したインターフェイスの実装

図 8 からわかるように、Visual Studio .NET は SmartTags を提供して、指定されたインターフェイスを実装します。 Visual Studio .NET 2003 からの主要な機能向上の 1 つは、明示的なインターフェイス実装を活用できるようになったことです。 ここでわかるように、このテクニックはオブジェクト レベルからインターフェイス メンバを隠し、それによって、呼び出し側がインターフェイス参照を直接取得できるようにします。

パラメータの再順序付け

[Reorder Parameters] リファクタリングは、ここまで説明してきた例よりも動機付けが少々難しいものです。 予想できるように、このリファクタリングはメンバの引数の順序を変更できるます。しかし、いつそのようにする必要があるでしょうか。 オーバーロードされたメソッドを含む型を作成し、それらが System.Drawing.Graphics 型を使用します。

class ImageRenderer
{
  public void Render(Point topLeft, Point bottomRight, Graphics g)
  { /* 関連するコード */ }
  public void Render(Graphics g, int x, int y)
  { /* 関連するコード */ }
  public void Render(Graphics g, Rectangle boundingBox)
  { /* 関連するコード */ }
}

2 番目と 3 番目の Render() メンバでは、最初のパラメータとして Graphics 型を持っています。最初のバージョンでは、この引数が最後になっています。 この C# コードは構文的に正しいのですが、このオーバーロードされたメソッドの非対称の性質は、オブジェクトのユーザーに混乱を招く (または少なくとも扱いづらい) 可能性があります。.

[Reorder Parameters] リファクタリングを使用して、すばやく既存のモデルをクリーンアップできます。 変更するパラメータを含んでいるメソッドを選択して開始し、結果の SmartTag を使用して [Reorder Parameter] をアクティブにします。(図 9) 。

ms379618.vs2005_refactoring-fig9(ja-jp,VS.80).gif

図 9. [Reorder Parameter] リファクタリング SmartTag

その他の Visual Studio 2005 リファクタリング オプションと同様、この次には設定用のダイアログ ボックスが表示されます。 この場合、特定の引数をチェーンの上下に移動できます (図 10) 。

ms379618.vs2005_refactoring-fig10(ja-jp,VS.80).gif

図 10. System.Drawing.Graphics パラメータの位置の変更

次の更新が表示されます。

class ImageRenderer
{
  public void Render(Graphics g, Point topLeft, Point bottomRight)
  { /* 関連するコード */ }
  public void Render(Graphics g, int x, int y)
  { /* 関連するコード */ }
  public void Render(Graphics g, Rectangle boundingBox)
  { /* 関連するコード */ }
}
メモ   .NET デザイン ガイドラインでは、一貫した順序で引数をオーバーロードに配置するようにも推奨されています。

パラメータの削除

[Remove Parameters] リファクタリングは、名前がその内容を説明しています。 既存のパラメータがメソッドの署名から削除されます。 説明のために、Render() メソッドから 2 番目の Point パラメータを削除するものと想定します (図 11) 。

ms379618.vs2005_refactoring-fig11(ja-jp,VS.80).gif

図 11. [Remove Parameter] リファクタリング SmartTag

この時点で、(再度) 設定用のダイアログが表示され、削除するパラメータを選択できます (図 12) 。

ms379618.vs2005_refactoring-fig12(ja-jp,VS.80).gif

図 12. 当該のパラメータの削除

予想できると思いますが、パラメータを削除するよう選択する場合は、このリファクタリングよってメソッドの呼び出しすべてに影響があることを想定すると、このリファクタリングの結果を確認することが特に重要になります (図 13) 。

ms379618.vs2005_refactoring-fig13(ja-jp,VS.80).gif

図 13. パラメータの削除のスコープを表示

名前の変更

[Rename] リファクタリングも非常に単純なものです。 名前空間、型、メンバ、またはパラメータの名前を新しいものに変更します。 [Rename] リファクタリングの主要な利点の 1 つが、開発者が最初に正しい名前を付ける責任を負わなくて済むという点です。 説明のために、次のように ImageRenderer 型を使用するところから開始する必要があります。

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace RefactoringExamples
{
   class ImageRenderer
   {
      public void Render(Graphics g, Point topLeft)
      { /* 関連するコード */ }
      public void Render(Graphics g, int x, int y)
      { /* 関連するコード */ }
      public void Render(Graphics g, Rectangle boundingBox)
      { /* 関連するコード */ }
   }

   class Program
   {
      static void Main(string[] args)
      {
         ImageRenderer imgObj = new ImageRenderer();
      }
   }
}

しばらく考えてから、(ImageRenderer ではなく) Renderer がこの型により適合した名前であると判断しました。 手動による検索および置換の手法を使用する必要があるのではなく、[Rename] リファクタリングは、プロジェクト全体を通して選択したトークンの見つかったものすべての名前を信頼性の高い方法で変更します (図 14) 。

ms379618.vs2005_refactoring-fig14(ja-jp,VS.80).gif

図 14. [Rename] リファクタリングの適用

ローカル変数のパラメータへの昇格

メソッドを構築すると、ローカル変数のセットが呼び出し元によって提供される引数となったほうが適していることに気付く場合があります。 たとえば、特定の *.txt ファイルを解析のために開く、メソッドを作成した場合を想定します。

class Program
{
  public static void ParseTextFile()
  {
    // ローカル ディスクのファイルを開きます。
    string fileToParse = @"C:\myFile.txt";
    StreamReader sr = File.OpenText(fileToParse);

    // StreamReader を使用して解析を開始します。
  }

  static void Main(string[] args)
  {
    ParseTextFile();
  }
}

すべての必要な解析ロジックを実装すると、呼び出し元がローカル System.String を引数として渡すことができるようにした場合に、ParseTextFile() メソッドがさらに便利になると判断します。 [Promote Local Variable to Parameter] リファクタリングを入力します (図 15) 。

ms379618.vs2005_refactoring-fig15(ja-jp,VS.80).gif

図 15. メソッドのパラメータの形をローカル変数を使用して変更

このリファクタリングを選択すると、ParseTextFile() メソッドが更新されて System.String をパラメータとしてとるようになったことを確認できます。一方、"C:\myFile.txt" の値を渡すために、このメソッドの既存の呼び出しの形式が変更されました (これが元のローカル変数の値と想定した場合) 。

class Program
{
  public static void ParseTextFile(string fileToParse)
  {
    // ローカル ディスクのファイルを開きます。
    StreamReader sr = File.OpenText(fileToParse);

    // StreamReader を使用して解析を開始します。
  }

  static void Main(string[] args)
  {
    ParseTextFile(@"C:\myFile.txt");
  }
}

メソッド スタブの生成

最後に説明するリファクタリングは [Generate Method Stub] です。 このリファクタリングは、手動による入力速度より、高速に思考している場合に便利です。 指定された変数の情報の基本型を表示するメソッドを最終的には定義する必要があることを予期しながら、Main() メソッド内で入力をしている場合を想定します。 ObtainTypeInfo() という名前の付いたメソッドを定義していませんが、そのまま進行します。

static void Main(string[] args)
{
  Type t = typeof(Renderer);
  string typeInfo = ObtainTypeInfo(t);
  Console.WriteLine(typeInfo);
}

この時点で、これから生成する予定の ObtainTypeInfo() メソッドを選択し、[Generate Method Stub] リファクタリングを適用できます (図 16) 。

ms379618.vs2005_refactoring-fig16(ja-jp,VS.80).gif

図 16. 予期したメソッドに対するスタブ コードの生成

メソッド スタブが呼び出し側メソッドのコンテキストでどのように定義されるかに注意してください。このため、ObtainTypeInfo() が "private" および "static" に定義されます。

private static string DisplayTypeInfo(Type t)
{
  throw new NotImplementedException();
}
この時点で、NotImplementedException 型のスローを必要な実装ロジックと置換できます。 
private static string ObtainTypeInfo(Type t)
{
  string typeInfo = "";
  typeInfo += string.Format("Base class: {0}", t.BaseType.Name);
  typeInfo += string.Format("\nFull name: {0}", t.FullName);
  typeInfo += string.Format("\nNumber of methods: {0}", 
    t.GetMethods().Length);
  return typeInfo;
}

すばらしい! ここまでの説明でわかるように、Visual Studio 2005 では、既存のコードの形体を "より良く" するための便利な機能が多数提供されます。 また、この IDE では、コードのリファクタリングのプロセスを非常に単純にする、多くのメニュー オプション、キーストローク、およびマウス クリックが用意されています。

まとめ

リファクタリングとは、意図した機能を保持したまま、既存のコードのデザインに基づいて機能向上を行うプロセスです。 ここまでの説明でわかるように、Visual Studio 2005 は多数の一般的なリファクタリングに対するサポートを提供します。 さまざまな手法を使用して、予測可能な方法でコードの形体を変更できます。

Visual Studio 2005 では現在自動化されていない多数の確立されたリファクタリングが存在することは明らかです。また、詳細を学習する興味がある場合 (筆者が望んでいることですが) は、この ウェブサイト (英語) Non-MS link を参照してください。このサイトでは、このトピックに関する書籍 『Refactoring: Improving the Design of Existing Code』 ((Addison Wesley、1999 年) をサポートしています。

関連資料については、Visual Studio .NET 2003 用のリファクタリング プラグインを入手する場合は、次のリンクを参照してください。

 

執筆者紹介

Andrew Troelsen は、Intertech Training Non-MS link のコンサルタントでありトレーナーでもあります。 Andrew には、賞を受けた『C# and the .NET Platform Second Edition』 (2002 年 Apress) を含む多数の著作があります。 Troelsenは、(よりによって) MacTech Non-MS link の月刊コラムの執筆者でもありますが、現在の探究心の対象は、SSCLI、Portible.NET、および Mono CLI のディストリビューションを使用した、Unix ベース システムでの .NET 開発です。

© 2009 Microsoft Corporation. All rights reserved. 使用条件 | 商標 | プライバシー
Page view tracker