一次代码重构记录

先说前言:

最近在做一个预警的功能。其中包含两个表,一个预警主表,一个该预警对应岗位的子表,这两个表是一对多的关系。

现在要做的这个功能是要新增一个预警。

新增预警时,要对主表插入一条记录,对子表插入多条记录。主表的主键是预警GUID,子表是双主键,预警GUID+岗位GUID。

好,那么进入正题,这个功能实现起来不难。 第一次写完之后,我把对这两个表的数据插入和简单的校验都放在一个方法中。

其中,我觉得子表的数据集合的实体类生成方法,即预警岗位的实体类集合,可以写入一个方法里,就将其抽离成一个方法。

第一次实现的代码如下所示:

 1 public void WarningPenetrateLowcostTotalPrice(CTSalesOrder so, CTCompanyConfig cc, CVRoom room)
 2 {
 3     // 没有设置预警岗位时,不发送预警
 4     if (cc == null
 5         || cc.LowcostWarningStationIDList == null
 6         || cc.LowcostWarningStationIDList.Length == 0)
 7     {
 8         return;
 9     }
10 
11     var lowcostWarningStationIDList = cc.LowcostWarningStationIDList ?? "";
12     var plaView = new CTPenetrateLowcostWarningView();
13     var plasView = new CTPenetrateLowcostWarningStationView();
14     var lowcostWarningStations = lowcostWarningStationIDList.Split(',');
15     var newPenetrateLowcostWarningGUID = Guid.NewGuid();
16     var isSuccess = true;
17 
18     var pla = new CTPenetrateLowcostWarning();
19     var plasList = 
20         plasView.BuildArray(newPenetrateLowcostWarningGUID, lowcostWarningStations);
21 
22     if (plasList == null || plasList.Count == 0)
23     {
24         return;
25     }
26                 
27     pla.PenetrateLowcostWarningGUID = newPenetrateLowcostWarningGUID;
28     pla.SourceGUID = so.SalesOrderGUID;
29     pla.SourceType = so.SalesOrderType == "S" ? "8" : "9";
30     pla.PenetrateTime = DateTime.Now;
31     pla.TotalPrice = so.SalesOrderTotalPrice;
32     pla.StandardTotalPrice = room.ForSaleTotalPrice;
33     pla.LowcostTotalPrice = room.LowcostTotalPrice;
34     pla.OperatorID = so.LastEditAccountGUID.GetValueOrDefault() != CRMCommon.gNullGuid ?
35         so.LastEditAccountGUID.GetValueOrDefault() : so.AddAccountGUID;
36 
37     using (DbTransaction trans = plaView.BeginTransaction())
38     {
39         try
40         {
41             isSuccess = isSuccess && plaView.Insert(pla, trans);
42             foreach (CTPenetrateLowcostWarningStation plas in plasList)
43             {
44                 isSuccess = isSuccess && plasView.Insert(plas, trans);
45                 if (!isSuccess)
46                 {
47                     break;
48                 }
49             }
50 
51             if (isSuccess)
52             {
53                 isSuccess = isSuccess && plaView.CommitTransaction(trans);
54             }
55             else
56             {
57                 plaView.CloseTransaction(trans);
58             }
59         }
60         catch(Exception)
61         {
62             plaView.CloseTransaction(trans);
63         }
64     }
65 }
第一次实现

其中抽离出的方法为:

 1 public class CTPenetrateLowcostWarningStationView : IDDBOperator<CTPenetrateLowcostWarningStation>
 2     {
 3         /// <summary>
 4         /// 构建预警岗位实体类集合
 5         /// </summary>
 6         /// <param name="penetrateLowcostWarningGUID"></param>
 7         /// <param name="lowcostWarningStations"></param>
 8         /// <returns></returns>
 9         internal List<CTPenetrateLowcostWarningStation> BuildArray(Guid penetrateLowcostWarningGUID, string[] lowcostWarningStations)
10         {
11             if (lowcostWarningStations == null || lowcostWarningStations.Length == 0)
12             {
13                 return null;
14             }
15 
16             List<CTPenetrateLowcostWarningStation> plasList = new List<CTPenetrateLowcostWarningStation>();
17 
18             foreach (string stationGUID in lowcostWarningStations)
19             {
20                 plasList.Add(new CTPenetrateLowcostWarningStation()
21                 {
22                     PenetrateLowcostWarningGUID = penetrateLowcostWarningGUID,
23                     LowcostWarningStationGUID = CRMCommon.ToGUID(stationGUID),
24                     HasRead = "N"
25                 });
26             }
27 
28             return plasList;
29         }
30     }
BuildArray方法

--------------------------------------------------------------------------------------------------------------

感觉实现得还行,数数行数,65行,好像多了点。 我想了一下,发现主表的实体类的代码也能抽出来做成一个方法,抽出来后的代码为:

 1 public void WarningPenetrateLowcostTotalPrice(CTSalesOrder so, CTCompanyConfig cc, CVRoom room)
 2 {
 3     // 没有设置预警岗位时,不发送预警
 4     if (cc == null
 5         || cc.LowcostWarningStationIDList == null
 6         || cc.LowcostWarningStationIDList.Length == 0)
 7     {
 8         return;
 9     }
10 
11     var lowcostWarningStationIDList = cc.LowcostWarningStationIDList ?? "";
12     var plaView = new CTPenetrateLowcostWarningView();
13     var plasView = new CTPenetrateLowcostWarningStationView();
14     var lowcostWarningStations = lowcostWarningStationIDList.Split(',');
15     var newPenetrateLowcostWarningGUID = Guid.NewGuid();
16     var isSuccess = true;
17 
18     var pla = plaView.BuildEntityBySalesOrder(so, room);
19     var plasList = plasView.BuildArray(newPenetrateLowcostWarningGUID, lowcostWarningStations);
20 
21     if (plasList == null || plasList.Count == 0)
22     {
23         return;
24     }
25 
26     using (DbTransaction trans = plaView.BeginTransaction())
27     {
28         try
29         {
30             isSuccess = isSuccess && plaView.Insert(pla, trans);
31             foreach (CTPenetrateLowcostWarningStation plas in plasList)
32             {
33                 isSuccess = isSuccess && plasView.Insert(plas, trans);
34                 if (!isSuccess)
35                 {
36                     break;
37                 }
38             }
39 
40             if (isSuccess)
41             {
42                 isSuccess = isSuccess && plaView.CommitTransaction(trans);
43             }
44             else
45             {
46                 plaView.CloseTransaction(trans);
47             }
48         }
49         catch(Exception)
50         {
51             plaView.CloseTransaction(trans);
52         }
53     }
54 }
第二次实现

这次抽离出的方法是plaView.BuildEntityBySalesOrder,代码如下:

 1  /// <summary>
 2         /// 用销售单实体类来构建预警实体类
 3         /// </summary>
 4         /// <param name="so"></param>
 5         /// <param name="room"></param>
 6         /// <returns></returns>
 7         internal CTPenetrateLowcostWarning BuildEntityBySalesOrder(CTSalesOrder so, CVRoom room)
 8         {
 9             if (so == null || room == null)
10             {
11                 return null;
12             }
13 
14             return new CTPenetrateLowcostWarning()
15             {
16                 PenetrateLowcostWarningGUID = Guid.NewGuid(),
17                 SourceGUID = so.SalesOrderGUID,
18                 SourceType = so.SalesOrderType == "S" ? "8" : "9",
19                 PenetrateTime = DateTime.Now,
20                 TotalPrice = so.SalesOrderTotalPrice,
21                 StandardTotalPrice = room.ForSaleTotalPrice,
22                 LowcostTotalPrice = room.LowcostTotalPrice,
23                 OperatorID = so.LastEditAccountGUID.GetValueOrDefault() != CRMCommon.gNullGuid ?
24                     so.LastEditAccountGUID.GetValueOrDefault() : so.AddAccountGUID,
25             };
26         }
BuildEntityBySalesOrder

--------------------------------------------------------------------------------------------------------------

好了,再数数行数,54行,只少了10行。这时我第一感觉好像已经没办法再少了。 再看看代码,发现占了最多行数的是保存的动作。对了,保存也能弄成个方法,

然后我就再拆,拆成如下:

 1 public void WarningPenetrateLowcostTotalPrice(CTSalesOrder so, CTCompanyConfig cc, CVRoom room)
 2         {
 3             // 没有设置预警岗位时,不发送预警
 4             if (cc == null
 5                 || cc.LowcostWarningStationIDList == null
 6                 || cc.LowcostWarningStationIDList.Length == 0)
 7             {
 8                 return;
 9             }
10 
11             var plaView = new CTPenetrateLowcostWarningView();
12             var plasView = new CTPenetrateLowcostWarningStationView();
13             
14             var lowcostWarningStationIDList = cc.LowcostWarningStationIDList ?? "";           
15             var lowcostWarningStations = lowcostWarningStationIDList.Split(',');
16             var pla = plaView.BuildEntityBySalesOrder(so, room);
17             var plasList = plasView.BuildArray(pla.PenetrateLowcostWarningGUID, lowcostWarningStations);
18 
19             plaView.AddWarning(pla, plasList);             
20         }
第三次视线

这次是将保存操作抽离成方法AddWarning,代码如下:

 1 internal void AddWarning(CTPenetrateLowcostWarning warning, List<CTPenetrateLowcostWarningStation> warningStations)
 2         {
 3             if (warning == null || warningStations == null || warningStations.Count == 0)
 4             {
 5                 return;
 6             }
 7 
 8             var isSuccess = true;
 9             var plasView = new CTPenetrateLowcostWarningStationView();
10 
11             using (DbTransaction trans = this.BeginTransaction())
12             {
13                 try
14                 {
15                     isSuccess = isSuccess && this.Insert(warning, trans);
16                     foreach (var station in warningStations)
17                     {
18                         isSuccess = isSuccess && plasView.Insert(station, trans);
19                         if (!isSuccess)
20                         {
21                             break;
22                         }
23                     }
24 
25                     if (isSuccess)
26                     {
27                         isSuccess = isSuccess && this.CommitTransaction(trans);
28                     }
29                     else
30                     {
31                         this.CloseTransaction(trans);
32                     }
33                 }
34                 catch (Exception)
35                 {
36                     this.CloseTransaction(trans);
37                 }
38             }
39         }
AddWarning方法

--------------------------------------------------------------------------------------------------------------

在数数行数,主方法的行数已经降到19行。这次我总算是满意了,也没有再抽方法的冲动,好了,这个方法完工。

其中各抽出来的方法中,只有AddWarning方法要接近40行。其他都是20左右。

总结一下,这个主方法从接近70行减少到19行。对这个结果我自己就不做什么评论了。

欢迎大家回复关于重构、优化、精简代码的建议。 对于我的重构,觉得不对的地方也欢迎指正。

原文地址:https://www.cnblogs.com/bee0060/p/3472546.html