深入浅出设计守则2

深入浅出设计守则2

小明收到需求, 需求如下:

麦当鸡系统需要统计消费次数的报表, 报表内容需要列出每一种消费种类的消费次数.

麦当鸡系统中有一个消费种类Enum 叫做ChargeType

public enum ChargeType {   DuckNuggets,   ChickenNuggets,   FrenchFries,   FriedChickenChops,   GreenBeanSoup}

小明写了统计方法

public ChargeStatistics Compute(ChargeType[] chargeHistory){   var data = new ChargeStatistics();   foreach (var r in chargeHistory)    {      if (r == ChargeType.DuckNuggets)         data.DuckNuggets++;      else if (r == ChargeType.ChickenNuggets)         data.ChickenNuggets++;      else if (r == ChargeType.FrenchFries)         data.FrenchFries++;      else if (r == ChargeType.FriedChickenChops)         data.FriedChickenChops++;      else if (r == ChargeType.GreenBeanSoup)         data.GreenBeanSoup++;   }   return data;}

可以改进的地方

观察上述的程式码, 可以发现到

有重複的程式码如果要新增ChargeType 的种类, 要修改统计的程式码

设计守则 如果你有大量的资料型别的资料, 就考虑可能将资料组织起来,形成一个物件类.
集合资料的方法有很多种, 资料结构可以用阵列也可以利用集合(List/Dictionary/...).

故统计的结果物件可以修改为

public class ChargeStatistics{   public Dictionary<ChargeType, int> Data { get; set; }}

然后在统计方法内改写为

public ChargeStatistics Compute(ChargeType[] chargeHistory){   var result = new ChargeStatistics();   foreach (var r in chargeHistory)    {      IncreaseCounter(result.Data, r);   }   return result;}private void IncreaseCounter(Dictionary<ChargeType, int> data, ChargeType chargeType){   if (!data.TryGetValue(r, out var counter))   {      data[r] = 1;   }   else   {      data[r] = counter + 1;   }}

我们可以直接使用Dictionary 字典的特性, 来统计计算每一种消费种类的次数.

在IncreaseCounter 方法中, 检查data 是否出现了某个ChargeType ,

如果有, 则对应的ChargeType 计数自增如果没有, 则对应的ChargeType 计数 = 1

LINQ 查询语法 (LINQ Query Syntax)

在整理资料的时候常常都需要给资料做分组, 以便更进一步的分析及处理,
而C# 有提供分组统计的方法, 我们可以拿来利用.

我们可以利用LINQ Group 语法将chargeHistory 资料做分组, 然后再用Count() 方法统计次数
故Compute() 方法可以改写为

public ChargeStatistics Compute(ChargeType[] chargeHistory){   var result = new ChargeStatistics();   var q1 = from tb1 in chargeHistory         group tb1 by tb1 into g1         select new         {            Key = g1.Key,            Count = g1.Count()         };   result.Data = q1.ToDictionary(x => x.Key, x => x.Count);   return result;}

LINQ 方法语法 (LINQ Method Syntax)

当然假如你不喜欢这种长得有点像SQL 语法的运算式, 你也能改写为Linq Method

public ChargeStatistics Compute(ChargeType[] chargeHistory){   var result = new ChargeStatistics();   var q1 = chargeHistory.GroupBy(x => x)         .Select(new          {            Key = g1.Key,            Count = g1.Count()         });   result.Data = q1.ToDictionary(x => x.Key, x => x.Count);   return result;}

让程式码会说话

最后在这个 "统计结果物件" 这个地方, Data 属性的宣告有点模糊,

public class ChargeStatistics{   public Dictionary<ChargeType, int> Data { get; set; }}

对于不熟悉麦当鸡系统的维护人员可能会不知道这个 Dictionary<ChargeType, int> 里面的 int 代表的是甚么意思.

故我们可以新增一个物件来明确宣告 "一个 ChargeType 的统计资料"

public class ChargeTypeStatistic{   public ChargeType ChargeType { get; set; }   public int Count { get; set; }}

然后宣告Data 属性为List ,
这样就可以明确让维护人员知道这个Data 的定义

public class ChargeStatistics{   public List<ChargeTypeStatistic> Data { get; set; }}

当然统计方法也要修改为下面方式

public ChargeStatistics Compute(ChargeType[] chargeHistory){   var result = new ChargeStatistics();   result.Data = chargeHistory.GroupBy(x => x)         .Select(new ChargeTypeStatistic         {            ChargeType = g1.Key,            Count = g1.Count()         })         .List();   return result;}

如此一来维护人员也比较清楚知道统计结果物件里面的代表意义,
对程式码的理解将不必再依靠繁杂的注解和厚厚的文件.


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章