《重构-改善既有代码设计》案例之C#版(3)
书接上文
在这个Statement方法中金额、积分、结果字符串已经相对统一了。还有一个美元格式化变量格格不入,每次用到它的时候都是string.Format(nfi, "{0:C}", AmountFor(perf) / 100)是不是代码也比较不易于理解。所以想到一个办法,继续提炼这个美元格式化代码
1 private string Usd(int aNumber) 2 { 3 NumberFormatInfo nfi = new CultureInfo("en-US").NumberFormat; 4 nfi.CurrencyDecimalDigits = 2; 5 return string.Format(nfi, "{0:C}", aNumber / 100); 6 }
这个方法名字Usd可谓精髓,一眼就知道是干啥的
所以Statement就变成这样了(勘误:总金额不用再除100了)
1 public string Statement() 2 { 3 int totalAmount = 0; 4 int volumeCredits = 0; 5 string result = $"Statement for {_invoice.Customer} \n"; 6 7 foreach (var perf in _invoice.performances) 8 { 9 volumeCredits += VolumeCreditsFor(perf); 10 //print line for this order 11 result += $"{PlayFor(perf).name}: {Usd(AmountFor(perf))}({perf.audience}seats)\n"; 12 totalAmount += AmountFor(perf); 13 } 14 15 result += $"Amount owed is {Usd(totalAmount / 100)}\n"; 16 result += $"You earned {volumeCredits} credits \n"; 17 return result; 18 }
如果是我的话,我最多也就只能想到这里了。。。但是大神就是大神。
现在这个foreach循环里,干了三件事。大神拆成了3个foreach,然后把变量移动,紧挨这使用到他们的地方。(勘误:总金额不用再除100了)
1 public string Statement() 2 { 3 int volumeCredits = 0; 4 foreach (var perf in _invoice.performances) 5 { 6 volumeCredits += VolumeCreditsFor(perf); 7 } 8 9 int totalAmount = 0; 10 foreach (var perf in _invoice.performances) 11 { 12 totalAmount += AmountFor(perf); 13 } 14 15 string result = $"Statement for {_invoice.Customer} \n"; 16 foreach (var perf in _invoice.performances) 17 { 18 result += $"{PlayFor(perf).name}: {Usd(AmountFor(perf))}({perf.audience}seats)\n"; 19 } 20 21 result += $"Amount owed is {Usd(totalAmount / 100)}\n"; 22 result += $"You earned {volumeCredits} credits \n"; 23 return result; 24 }
然后把计算总积分,总金额的代码又提炼了两个方法
1 private int TotalAmount() 2 { 3 int result = 0; 4 foreach (var perf in _invoice.performances) 5 { 6 result += AmountFor(perf); 7 } 8 9 return result; 10 } 11 12 private int TotalVolumeCredits() 13 { 14 int result = 0; 15 foreach (var perf in _invoice.performances) 16 { 17 result += VolumeCreditsFor(perf); 18 } 19 20 return result; 21 }
再使用内联变量的手法 (勘误:总金额不用再除100了)
1 public string Statement() 2 { 3 string result = $"Statement for {_invoice.Customer} \n"; 4 foreach (var perf in _invoice.performances) 5 { 6 result += $"{PlayFor(perf).name}: {Usd(AmountFor(perf))}({perf.audience}seats)\n"; 7 } 8 9 result += $"Amount owed is {Usd(TotalAmount() / 100)}\n"; 10 result += $"You earned {TotalVolumeCredits()} credits \n"; 11 return result; 12 }
如此一来Statement只处理结果字符串,计算金额和积分的代码不再搅合在一起了(但仍然使用到了计算金额,积分的方法),只剩下了几行代码
大神下一步的思路就是使得计算阶段和格式化输出阶段分离。
本篇完成...待续....