寫Kata或產品代碼時,有時候會發現有些變數他們總是一起出現,例如下面這個例子
...
public string GetScore(double x, double y)
{
var mangi = GetMagniByPosition(x, y);
var score = _fixResultMagni.Contains(mangi) ? "" : GetScoreByPosition(x, y);
return mangi + score;
}
private string GetMagniByPosition(double x, double y)
{
var distance = GetDistance(x, y);
return _magniDistanceDict.FirstOrDefault(entry => entry.Key.IsThisDistance(distance)).Value;
}
private string GetScoreByPosition(double x, double y)
{
var angle = GetAngle(x, y);
return Convert.ToString(_scoreAngleDict.First(entry => entry.Key.IsThisRange(angle)).Value);
}
...
這是一個計算飛鏢分數的一段代碼,飛鏢位置傳入GetScore(x, y)並依照不同區域給予相應的分數。因為不管計算角度或者是距離,計算都會需要使用到飛鏢的橫坐標與縱座標,所以x, y不斷的重複出現在每個方法中,這也是眾多代碼壞味道的其中之一:Data Clumps(資料泥團)。想了解更多代碼的壞味道,建議可以去看 重構|改善既有程式的設計 2/e
所以更好的作法應該是把x, y抽取成一個類別,以上面的例子來說把他們抽成Point類別就是一個不錯的選擇。假設今天是想表示一個多維度空間的點,把他們抽取成一個類別,就能讓使用到的地方只傳入一個類別就好,不然就會讓這些變數散開在哪每個使用到的地方。
...
public string GetScore(Point point)
{
var mangi = GetMagniByPosition(point);
var score = _fixResultMagni.Contains(mangi) ? "" : GetScoreByPosition(point);
return mangi + score;
}
private string GetMagniByPosition(Point point)
{
var distance = GetDistance(point);
return _magniDistanceDict.FirstOrDefault(entry => entry.Key.IsThisDistance(distance)).Value;
}
private string GetScoreByPosition(Point point)
{
var angle = GetAngle(point);
return Convert.ToString(_scoreAngleDict.First(entry => entry.Key.IsThisRange(angle)).Value);
}
...
值得一提的是,當我們把這些變數抽成一個x, y類別之後,又出現了其他的壞味道,是在我們沒有解決資料泥團之前比較難看出來的壞味道,這個我們之後會再用這個例子進一步解釋。
除了x, y, z這種座標類型的,還有一些容易出現資料泥團壞味道的資料類型,像是
其他還有像是網球比賽雙方的得分數之類的,都有可能會有資料泥團的壞味道。