我們在方法裡面很常宣告變數來暫存一些計算結果,在之後我們也會在拿著這些計算結果在與其他結果一起運算產生回傳值。這些暫存變數宣吿只要宣告在使用之前,編譯器就不會報錯,但是宣告的位置不適合卻會十分影響閱讀。
以下面這個方法為例,smallerDigits在方法一開始的地方就宣告了,使用的地方卻是在if判斷式裡面,但是smallerDigits最晚是可以在if判斷式之前宣告就好。
private List<long> FindSmaller(List<long> digits)
{
var smallerDigits = new List<long>();
var firstDigit = digits[0];
var otherDigits = digits.Skip(1).ToList();
if (IsSmallest(otherDigits))
{
var sortedDigits = digits.OrderByDescending(i => i).ToList();
var secondLargeDigit = sortedDigits.First(i => i < firstDigit);
sortedDigits.RemoveAt(sortedDigits.IndexOf(secondLargeDigit));
smallerDigits.Add(secondLargeDigit);
smallerDigits.AddRange(sortedDigits);
}
else
{
smallerDigits.Add(firstDigit);
smallerDigits.AddRange(FindSmaller(otherDigits));
}
return smallerDigits.ToList();
}
這個例子裡面宣告的地方與最晚可以宣告的地方隔了兩行,想像一下,如果在產品代碼中他隔了超過了一個畫面的距離,那閱讀代碼時候就得時時刻刻注意這個變數是否遭到更改。
我們稍微換一下位置,讓smallerDigits與使用他的if判斷式相鄰,這樣不管smallerDigits前面有少代碼,我們都能清楚知道smallerDigits只會跟他往下的代碼有關係。閱讀的時候我們的腦中就可以少記一些資訊。
private List<long> FindSmaller(List<long> digits)
{
var firstDigit = digits[0];
var otherDigits = digits.Skip(1).ToList();
var smallerDigits = new List<long>();
if (IsSmallest(otherDigits))
{
var sortedDigits = digits.OrderByDescending(i => i).ToList();
var secondLargeDigit = sortedDigits.First(i => i < firstDigit);
sortedDigits.RemoveAt(sortedDigits.IndexOf(secondLargeDigit));
smallerDigits.Add(secondLargeDigit);
smallerDigits.AddRange(sortedDigits);
}
else
{
smallerDigits.Add(firstDigit);
smallerDigits.AddRange(FindSmaller(otherDigits));
}
return smallerDigits.ToList();
}
讓宣告變數的地方移動到使用的地方還有另外一個好處:因為使用的地方通常與宣告的地方緊緊相鄰,所以我們更容易看出哪些變數與使用端相依,我們更好把這些相依的代碼透過抽取方法來讓方法變得更乾淨。如果變數宣告的地方與使用的地方離得太遠,腦袋在閱讀的時候不容易把他們產生連結,通常會需要反覆的來回查看,就會花更多時間。