後編 Visual Studio 2017のリファクタリング機能:特集:Visual Studioで始めるリファクタリング(2/4 ページ)
変数レベル/メソッドレベル/型レベルでのリファクタリングを支援するために、Visual Studio 2017が提供している機能を取り上げる。
変数レベルのリファクタリング
変数のリファクタリングに関しては、前編で紹介した「名前の変更」の他に、説明用変数の導入やインライン化などがサポートされている。
『説明用変数の導入』(Extract Variable)
変数に代入したい式を指定し(次のコード)、[Ctrl]+[,]を押すなどしたら、リファクタリングサポート機能の[{指定部分} に対してローカルを導入します]または[{指定部分} のすべての発生に対してローカルを導入します]を選ぶ*1。
string result;
if (n % 3 == 0)
{
if (n % 5 == 0)
result = "Fizz Buzz";
else
result = "Fizz";
}
else
{
if (n % 5 == 0)
result = "Buzz";
else
result = n.ToString();
}
太字にした「n % 5 == 0」の部分を選択して、「すべての発生に対してローカルを導入」を行う。後半にも(選択していない)「n % 5 == 0」があることに注意。
仮の変数名をリネームした後の結果は、次のコードのようになる。
string result;
bool isMultipleOf5 = n % 5 == 0;
if (n % 3 == 0)
{
if (isMultipleOf5)
result = "Fizz Buzz";
else
result = "Fizz";
}
else
{
if (isMultipleOf5)
result = "Buzz";
else
result = n.ToString();
}
元のコードの「n % 5 == 0」の部分が2箇所とも、新しく導入した変数「isMultipleOf5」に置き換わった。
*1 英語の原文:
- Introduce local for '{指定部分}'
- Introduce local for all occurrences of '{指定部分}'
ここで「occurrence」は「出現」の意。後者は、指定した部分だけでなく、同じ部分を探し出して全てを新しく導入する変数に置き換える。
『一時変数のインライン化』(Inline Temp)
『説明用変数の導入』とは逆向きの機能である。
インライン展開したい変数を指定し、リファクタリングサポート機能の[インラインの一時変数]を選ぶ*2。この例に示すように、単純な展開だけでなく、C# 7の新機能「パターンマッチング」を使った書き換えもサポートされている(次のコードはこの機能を使って、リファクタリング前のコードにあった一時変数をインラインに展開したものだ)。
// リファクタリング前
public static void SampleMethod1(Shape s)
{
var e = s as Ellipse;
if (e != null && e.Width == e.Height)
WriteLine("真円です");
else
WriteLine("真円ではありません");
}
// ↓
// リファクタリング後
public static void SampleMethod1(Shape s)
{
if (s is Ellipse e && e.Width == e.Height)
WriteLine("真円です");
else
WriteLine("真円ではありません");
}
宣言している部分で変数「e」を選択して、[インラインの一時変数]を選ぶ。すると通常は、変数「e」に代入している右辺を使って、以降の変数「e」の使用箇所が置き換えられる。ただし、is演算子の型パターンが使える場合には、このようにパターンマッチングを使った書き換えも可能だ(パターンマッチを使える場合には、それを使って一時変数を展開する選択肢と、パターンマッチを行わない選択肢が提案される)。
*2 英語の原文:
- Inline temporary variable
試訳:「一時変数をインライン化する」
『フィールドのカプセル化』(Encapsulate Field)
プロパティに変換したいフィールド(メンバ変数)を指定し、リファクタリングサポート機能の[フィールドのカプセル化]を選ぶ*3(次のコードはこの機能を使ってFirstNameフィールドをプロパティにカプセル化したものだ)。
// リファクタリング前
public string FirstName;
public string LastName;
public string GetName()
=> $"{FirstName} {LastName}";
// ↓
// リファクタリング後
private string firstName;
public string LastName;
public string FirstName { get => firstName; set => firstName = value; }
public string GetName()
=> $"{FirstName} {LastName}";
プロパティに変更したいフィールドを指定して[フィールドのカプセル化]を選ぶ。このとき、クラス内でそのフィールドを参照している部分を、フィールドの参照のままにするか、新しく作ったプロパティを参照するように変更するのかを選べる*3。
この例は、フィールドを参照している部分をプロパティの参照に変更するように指定した場合だ。
*3 「フィールドのカプセル化」のメニューには、正確には次の2つがある:
- [フィールドのカプセル化: '{対象メンバ名}' (およびプロパティを使用します)](英語表記は「Encapsulate field '{対象メンバ名}' (and use property)」)
- [フィールドのカプセル化: '{対象メンバ名}' (ただし、フィールドを継続して使用します)](英語表記は「Encapsulate field '{対象メンバ名}' (but still use field)」)
上の例では、前者を使っている。
次にVS 2017のリファクタリングサポート機能を使って、メソッドレベルのリファクタリングを行う方法を見てみる。
Copyright© Digital Advantage Corp. All Rights Reserved.