国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

對設計及重構的一點反思

開發 架構
本項目是一個電子商務類的網站,其中有個功能是在訂單狀態改變到某種狀態后向客戶發送通知短信的功能,短信及網關功能均已封裝為組建的方式,我們直接調用即可。

本文是我對一個項目中一個小功能點的演進及重構過程的一點反思與心得。

背景:

本項目是一個電子商務類的網站,其中有個功能是在訂單狀態改變到某種狀態后向客戶發送通知短信的功能,短信及網關功能均已封裝為組建的方式,我們直接調用即可。

為更清晰明白地說明與本主題相關的功能,在此我以一個控制臺的程序方式說明代碼的演進過程。

重構的演進過程:

最初我們是如大多數項目一樣,為在規定的時間內完成相關功能點而努力奮斗著,這個功能點的主要代碼如下:

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

在項目上線初期,這段代碼工作良好。

在運營一段時間后運營部門同事陸續提出要在某些地方將產品名稱給加上去,在這一改動過程中,我發現代碼沒有和數據相分離,再者如要增加一個訂單狀態后增加相應的短信提示或者取消某一個狀態的短信提示,這個改動過程有點麻煩。于是初步想到將短信的內容放到配置文件中,在調用的時候讀取訂單狀態對應的配置文件然后格式化即可。如讀取的內容為空或者該文件不存在則跳過不發送。主要代碼如下:

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

模版

  1. 尊敬的{0},你好!你的訂單(訂單號:{1})已被確認,請耐心等待。 

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

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

模版

  1. 尊敬的{0:CustomerName},你好!你的訂單(訂單號:{0:OrderID},產品:產品{0:productname})已被確認,請耐心等待。 

將數據字段取出來后寫成一個標簽列表文檔提供給運營人員后,從此關于這一塊的修改要求安靜了。

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

一點疑問:

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

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

原文鏈接:http://www.cnblogs.com/infozero/archive/2013/03/05/2944106.html

責任編輯:林師授 來源: 博客園
相關推薦

2015-12-04 15:39:27

產品服務反思

2014-09-17 10:30:25

代碼

2021-05-17 11:47:41

多租戶系統私有化

2015-11-02 09:43:25

ASP.NET異步編程

2010-05-20 15:29:43

優化IIS

2009-04-13 11:50:14

經驗交流職業分析面試

2013-05-13 11:25:44

系統架構

2013-05-14 12:06:26

.Net系統架構架構設計

2012-03-27 08:49:19

Json

2009-07-09 15:09:05

JDK卸載

2009-09-14 19:44:27

LINQ To SQL

2009-07-22 14:53:45

ibmdwIT架構

2025-05-29 00:00:00

UI 庫前端模塊化

2016-04-05 10:12:58

HiveSQLHadoop

2024-05-31 08:40:09

2016-01-06 09:49:59

青云/SDN

2014-06-04 10:48:38

Swift蘋果iOS

2009-09-14 20:17:05

并行LINQ

2012-07-12 10:49:53

項目管理

2011-07-04 09:33:04

惠普轉型李艾科
點贊
收藏

51CTO技術棧公眾號

一区二区三区在线电影| 免费**毛片在线| 99国产成+人+综合+亚洲欧美| 8x拔播拔播x8国产精品| 第四色男人最爱上成人网| 欧美电影影音先锋| 污网站免费在线观看| 亚洲欧美日韩一区二区| 北条麻妃在线视频观看| 久久国内精品自在自线400部| 成人免费视频视频在| 亚洲综合激情在线| 国产欧洲精品视频| 成人羞羞网站入口| 欧美最猛黑人xxxx黑人猛叫黄| 国产精品porn| 成人国产在线视频| 午夜精品福利影院| 欧美中文字幕一区| 日本成人三级电影网站| 色噜噜久久综合伊人一本| 久久综合色影院| 东京一区二区| 日韩精品免费视频| 涩涩av在线| 国产亚洲精品成人av久久ww| 欧美黑人一区| 在线观看欧美日韩| www.久久久.com| 国模精品视频一区二区| 国产成人精品影视| 黄色一级片网址| 成人看的视频| 欧美精品成人91久久久久久久| 亚洲人成网www| 久久午夜a级毛片| 哺乳挤奶一区二区三区免费看| 久久久久九九九九| 美女久久99| 97影院在线午夜| 日韩 欧美一区二区三区| 老司机av福利| 国产日韩欧美高清| 成r视频免费观看在线播放| 欧美性高潮在线| a级在线观看| 国产亚洲精品日韩| 看全色黄大色大片免费久久久| 国产精品永久免费| 蘑菇福利视频一区播放| 美女av免费观看| 亚洲美女在线国产| 91xxx在线观看| 国产偷亚洲偷欧美偷精品| 激情视频亚洲| 亚洲r级在线观看| 久久精品二区亚洲w码| www欧美激情| 欧美在线综合视频| 天堂中文最新版在线中文| 国内免费精品永久在线视频| 午夜天堂精品久久久久| 日韩视频在线免费播放| 国产日韩影视精品| 尤物在线视频| 久久久成人精品| 中文字幕一区二区av | 国内精品久久久| 韩日在线一区| 熟女性饥渴一区二区三区| 日本精品一级二级| 日韩三级成人| 韩国成人一区| 亚洲欧洲日韩女同| 日本免费一区二区六区| 国产精品成久久久久三级| 久久99国产精品尤物| 原千岁中文字幕| 正在播放欧美一区| 黄色在线成人| 久久久性生活视频| 欧美亚洲综合色| 国产丝袜一区| 天天操天天干天天玩| 亚洲综合久久av| 澳门av一区二区三区| 2022国产精品| 国产女人18毛片水真多成人如厕| 午夜影院免费在线| 国产精品www色诱视频| 成人免费视频一区二区| av播放在线| 国模叶桐国产精品一区| 麻豆国产欧美日韩综合精品二区| 在线黄色.com| 91地址最新发布| 川上优的av在线一区二区| 亚洲欧洲中文| 亚洲一区二区三区三| 亚洲成人高清| 日韩专区在线视频| 一区二区三区 日韩| 欧美一区二区三区四区视频| 日本在线成人| 亚洲国产一区二区三区在线播 | 在线伊人免费视频| 色偷偷88888欧美精品久久久| 韩国一区二区三区在线观看| 激情婷婷综合网| 欧美成人激情免费网| 欧美日本成人| 国产精品wwwww| 亚洲开心激情网| 久久高清免费观看| 在线人体午夜视频| 国自产精品手机在线观看视频| 裸体一区二区三区| 91免费在线| 国产有码在线一区二区视频| 国产欧美综合色| 久久婷婷五月综合色丁香| 午夜精品视频在线观看一区二区| 色诱亚洲精品久久久久久| 日韩成人一级| 免费午夜视频在线观看| 亚洲精品一区二区三区不| 夜夜嗨av一区二区三区网站四季av| aaaaaaa大片免费看| 美日韩在线视频| 成人精品免费视频| 欧美电影免费看| 伊人久久av导航| 亚洲成人在线网| 性感少妇一区| 丝袜美腿美女被狂躁在线观看| 国产精品男女猛烈高潮激情| 亚洲日本电影在线| 女一区二区三区| 疯狂做受xxxⅹ高潮视频免费| 欧美巨猛xxxx猛交黑人97人| 国产激情精品久久久第一区二区| 97在线视频免费观看完整版| 欧美一区二区高清在线观看| 欧美日本在线播放| 91久久中文| 国产日产一区二区| 国产区二精品视| 日韩精品一区二区三区在线观看 | 欧美成人一品| 精品福利视频导航大全| 91热福利电影| 色素色在线综合| 欧美成人一区二免费视频软件| 国产色在线 com| 国产亚洲一区二区三区在线播放| 欧美视频完全免费看| 日韩电影在线免费观看| 美女91在线看| 日韩在线一级片| 国语自产精品视频在线看抢先版图片| 国产精品久久久久久久蜜臀| 你微笑时很美电视剧整集高清不卡| 激情视频免费观看在线| 97se亚洲综合| 欧美精品一区二区高清在线观看| 成人免费毛片片v| 久久99国产精品久久99大师| 91欧洲在线视精品在亚洲| 亚洲www视频| 精品免费国产二区三区| 成人福利视频网站| 亚洲成aⅴ人片久久青草影院| 亚洲图区欧美| 色一情一区二区三区四区| 一区二区三区精品99久久| 国产日韩欧美精品电影三级在线 | 亚洲深夜av| 久久sese| 鲁一鲁一鲁一鲁一av| 国产日韩在线免费| 欧美tickling挠脚心丨vk| 99免费精品视频| 日韩欧美二区| 欧美大胆a人体大胆做受| 午夜精品在线免费观看| 91在线观看免费高清| 亚洲精品aⅴ中文字幕乱码| 国产婷婷色一区二区三区四区| 日本一区二区在线看| 成年网站在线视频网站| av成人网在线| 四虎影院一区二区三区 | 97碰碰碰免费色视频| 日韩欧美第一页| 国产成人在线看| 精品日本12videosex| 伊人久久国产| 午夜成在线www| 日韩欧美一区三区| 国内视频一区|