一次代码重构记录
先说前言:
最近在做一个预警的功能。其中包含两个表,一个预警主表,一个该预警对应岗位的子表,这两个表是一对多的关系。
现在要做的这个功能是要新增一个预警。
新增预警时,要对主表插入一条记录,对子表插入多条记录。主表的主键是预警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 }
--------------------------------------------------------------------------------------------------------------
感觉实现得还行,数数行数,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 }
--------------------------------------------------------------------------------------------------------------
好了,再数数行数,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 }
--------------------------------------------------------------------------------------------------------------
在数数行数,主方法的行数已经降到19行。这次我总算是满意了,也没有再抽方法的冲动,好了,这个方法完工。
其中各抽出来的方法中,只有AddWarning方法要接近40行。其他都是20左右。
总结一下,这个主方法从接近70行减少到19行。对这个结果我自己就不做什么评论了。
欢迎大家回复关于重构、优化、精简代码的建议。 对于我的重构,觉得不对的地方也欢迎指正。