先说前言:
最近在做一个预警的功能。其中包含两个表,一个预警主表,一个该预警对应岗位的子表,这两个表是一对多的关系。
现在要做的这个功能是要新增一个预警。
新增预警时,要对主表插入一条记录,对子表插入多条记录。主表的主键是预警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 try40 {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 else56 {57 plaView.CloseTransaction(trans);58 }59 }60 catch(Exception)61 {62 plaView.CloseTransaction(trans);63 }64 }65 }
其中抽离出的方法为:
1 public class CTPenetrateLowcostWarningStationView : IDDBOperator2 { 3 /// 4 /// 构建预警岗位实体类集合 5 /// 6 /// 7 /// 8 ///9 internal List BuildArray(Guid penetrateLowcostWarningGUID, string[] lowcostWarningStations)10 {11 if (lowcostWarningStations == null || lowcostWarningStations.Length == 0)12 {13 return null;14 }15 16 List plasList = new List ();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 try29 {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 else45 {46 plaView.CloseTransaction(trans);47 }48 }49 catch(Exception)50 {51 plaView.CloseTransaction(trans);52 }53 }54 }
这次抽离出的方法是plaView.BuildEntityBySalesOrder,代码如下:
1 ///2 /// 用销售单实体类来构建预警实体类 3 /// 4 /// 5 /// 6 ///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, ListwarningStations) 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 try14 {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 else30 {31 this.CloseTransaction(trans);32 }33 }34 catch (Exception)35 {36 this.CloseTransaction(trans);37 }38 }39 }
--------------------------------------------------------------------------------------------------------------
在数数行数,主方法的行数已经降到19行。这次我总算是满意了,也没有再抽方法的冲动,好了,这个方法完工。
其中各抽出来的方法中,只有AddWarning方法要接近40行。其他都是20左右。
总结一下,这个主方法从接近70行减少到19行。对这个结果我自己就不做什么评论了。
欢迎大家回复关于重构、优化、精简代码的建议。 对于我的重构,觉得不对的地方也欢迎指正。