日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
對(duì)設(shè)計(jì)及重構(gòu)的一點(diǎn)反思

本文是我對(duì)一個(gè)項(xiàng)目中一個(gè)小功能點(diǎn)的演進(jìn)及重構(gòu)過(guò)程的一點(diǎn)反思與心得。

成都創(chuàng)新互聯(lián)專注于印臺(tái)企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站定制開發(fā)。印臺(tái)網(wǎng)站建設(shè)公司,為印臺(tái)等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站策劃,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

背景:

本項(xiàng)目是一個(gè)電子商務(wù)類的網(wǎng)站,其中有個(gè)功能是在訂單狀態(tài)改變到某種狀態(tài)后向客戶發(fā)送通知短信的功能,短信及網(wǎng)關(guān)功能均已封裝為組建的方式,我們直接調(diào)用即可。

為更清晰明白地說(shuō)明與本主題相關(guān)的功能,在此我以一個(gè)控制臺(tái)的程序方式說(shuō)明代碼的演進(jìn)過(guò)程。

重構(gòu)的演進(jìn)過(guò)程:

最初我們是如大多數(shù)項(xiàng)目一樣,為在規(guī)定的時(shí)間內(nèi)完成相關(guān)功能點(diǎn)而努力奮斗著,這個(gè)功能點(diǎn)的主要代碼如下:

 
 
 
  1. v1 
  2.         static void SendSMS_V1(DataTable dt)
  3.         {
  4.             if (null == dt) return;
  5.             for (int i = 0; i < dt.Rows.Count; i++)
  6.             {
  7.                 var row = dt.Rows[i];
  8.                 OrderStateEnum state = (OrderStateEnum)((int)row["OrderState"]);
  9.                 string template = string.Empty;
  10.                 switch (state)
  11.                 {
  12.                     case OrderStateEnum.UnConfirmed:
  13.                         template = "尊敬的{0},你好!你的訂單已成功下達(dá),請(qǐng)盡快付款以便配送。";
  14.                         break;
  15.                     case OrderStateEnum.Confirmed:
  16.                         template = "尊敬的{0},你好!你的訂單(訂單號(hào):{1})已被確認(rèn),請(qǐng)耐心等待。";
  17.                         break;
  18.                     case OrderStateEnum.Cancel:
  19.                         template = "尊敬的{0},你好!你的訂單(訂單號(hào):{1})已被取消,具體原因請(qǐng)上網(wǎng)查看。";
  20.                         break;
  21.                     case OrderStateEnum.Finish:
  22.                         template = "尊敬的{0},你好!你的訂單(訂單號(hào):{1})已完成,網(wǎng)站感謝您的支持與配合,歡迎再次光臨。";
  23.                         break;
  24.                     default:
  25.                         break;
  26.                 }
  27.                 string content = string.Format(template, row["CustomerName"], row["OrderID"]);
  28.                 SendSMS.Send(row["phone"].ToString(), content);
  29.             }
  30.         }

在項(xiàng)目上線初期,這段代碼工作良好。

在運(yùn)營(yíng)一段時(shí)間后運(yùn)營(yíng)部門同事陸續(xù)提出要在某些地方將產(chǎn)品名稱給加上去,在這一改動(dòng)過(guò)程中,我發(fā)現(xiàn)代碼沒有和數(shù)據(jù)相分離,再者如要增加一個(gè)訂單狀態(tài)后增加相應(yīng)的短信提示或者取消某一個(gè)狀態(tài)的短信提示,這個(gè)改動(dòng)過(guò)程有點(diǎn)麻煩。于是初步想到將短信的內(nèi)容放到配置文件中,在調(diào)用的時(shí)候讀取訂單狀態(tài)對(duì)應(yīng)的配置文件然后格式化即可。如讀取的內(nèi)容為空或者該文件不存在則跳過(guò)不發(fā)送。主要代碼如下:

 
 
 
  1. v2 內(nèi)容和數(shù)據(jù)分離 
  2.         #region v2 內(nèi)容和數(shù)據(jù)分離 
  3.         static void SendSMS_V2(DataTable dt)
  4.         {
  5.             if (null == dt) return;
  6.             for (int i = 0; i < dt.Rows.Count; i++)
  7.             {
  8.                 var row = dt.Rows[i];
  9.                 string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SMSTemplates",
  10.                     "V2", row["OrderState"].ToString() + ".txt");
  11.                 var template = FileHelper.Read(path);
  12.                 if (!string.IsNullOrEmpty(template)) {
  13.                     string content = string.Format(template, row["CustomerName"], row["OrderID"], row["ProductName"]);
  14.                     SendSMS.Send(row["phone"].ToString(), content);
  15.                 }
  16.             }
  17.         }
  18.         #endregion

模版

 
 
 
  1. 尊敬的{0},你好!你的訂單(訂單號(hào):{1})已被確認(rèn),請(qǐng)耐心等待。

隨著運(yùn)營(yíng)進(jìn)行,運(yùn)營(yíng)部門不斷地提出將某些字段在某些地方顯示, string.Format 后的參數(shù)不斷地增加,每次改后都要將整個(gè)過(guò)程重新測(cè)試一通,很是讓人頭疼!我的想法是開發(fā)這邊提供一個(gè)數(shù)據(jù)標(biāo)簽列表,同時(shí)在后臺(tái)提供操作界面將短信管理模板讓運(yùn)營(yíng)同事自己去修改,不用每次都找我們?有了以上想法,使用一個(gè)自定義的 formatter :

 
 
 
  1. 自定義參數(shù)格式化 
  2.     public class IndexerNamedFormatter : IFormatProvider, ICustomFormatter
  3.     {
  4.         public IndexerNamedFormatter() { }
  5.         public object GetFormat(Type formatType)
  6.         {
  7.             if (formatType == typeof(ICustomFormatter))
  8.                 return this;
  9.             throw new TypeAccessException("不匹配的類型。");
  10.         }
  11.         public string Format(string format, object arg, IFormatProvider formatProvider)
  12.         {
  13.             if (null == arg)
  14.                 throw new ArgumentNullException("參數(shù) arg 不能為 null");
  15.             int indexer = 0;
  16.             bool isIndexed = int.TryParse(format, out indexer);
  17.             //如是 datarow 
  18.             if (arg is System.Data.DataRow)
  19.             {
  20.                 return GetStringFromDataRow(format, arg, indexer, isIndexed);
  21.             }
  22.             //如是 datareader 之類的
  23.             if (arg is System.Data.IDataRecord)
  24.             {
  25.                 GetStringFromIDataRecord(format, arg, indexer, isIndexed);
  26.             }
  27.             return string.Empty; ;
  28.         }
  29.         private static void GetStringFromIDataRecord(string format, object arg, int indexer, bool isIndexed)
  30.         {
  31.             var dr = (System.Data.IDataRecord)arg;
  32.             string.Format("{0}", isIndexed ? dr[indexer] : dr[format]);
  33.         }
  34.         string GetStringFromDataRow(string format, object arg, int indexer, bool isIndexed)
  35.         {
  36.             var row = (System.Data.DataRow)arg;
  37.             return string.Format("{0}", isIndexed ? row[indexer] : row[format]);
  38.         }
 
 
 
  1. v3 使用自定義標(biāo)簽 
  2. #region v3 使用自定義標(biāo)簽 
  3.         static void SendSMS_V3(DataTable dt)
  4.         {
  5.             if (null == dt) return;
  6.             IndexerNamedFormatter formatter = new IndexerNamedFormatter();
  7.             for (int i = 0; i < dt.Rows.Count; i++)
  8.             {
  9.                 var row = dt.Rows[i];
  10.                 string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SMSTemplates",
  11.                     "V3", row["OrderState"].ToString() + ".txt");
  12.                 var template = FileHelper.Read(path);
  13.                 if (!string.IsNullOrEmpty(template))
  14.                 {
  15.                     string content = string.Format(formatter,
  16.                         template, row);
  17.                     SendSMS.Send(row["phone"].ToString(), content);
  18.                 }
  19.             }
  20.         }
  21.         #endregion

模版

 
 
 
  1. 尊敬的{0:CustomerName},你好!你的訂單(訂單號(hào):{0:OrderID},產(chǎn)品:產(chǎn)品{0:productname})已被確認(rèn),請(qǐng)耐心等待。

將數(shù)據(jù)字段取出來(lái)后寫成一個(gè)標(biāo)簽列表文檔提供給運(yùn)營(yíng)人員后,從此關(guān)于這一塊的修改要求安靜了。

以上只是一個(gè)小小設(shè)計(jì)技巧,這也讓我明白需求的準(zhǔn)確把握與挖掘是何等地重要!往往客戶今天說(shuō)要這樣,明天要那樣,大概很多人都在抱怨:你們真麻煩!但在需求不斷地出現(xiàn)時(shí)我們是不是在修改的時(shí)候也反思下是不是我們未準(zhǔn)確把握他們所想要的功能而讓功能設(shè)計(jì)出了點(diǎn)問(wèn)題?當(dāng)然我也不崇尚一開始就大談設(shè)計(jì),過(guò)度設(shè)計(jì)要付出大量的時(shí)間成本和可能導(dǎo)致實(shí)現(xiàn)的復(fù)雜度的增加。

一點(diǎn)疑問(wèn):

通過(guò)查閱文檔我一直感覺 arg is System.Data.DataRow 這種實(shí)現(xiàn)方式很是別扭,為什么索引器不定義為一個(gè)接口 ?有誰(shuí)有更好的實(shí)現(xiàn)方法麻煩告知,謝謝!

感謝您的閱讀!文中所涉及到的代碼可從此下載。


當(dāng)前名稱:對(duì)設(shè)計(jì)及重構(gòu)的一點(diǎn)反思
文章位置:http://m.5511xx.com/article/dppihih.html