標籤:des style blog http color io os 使用 ar
前言
既然作為一個踏踏實實學習技術的人,就要有一顆謙卑、虛心和追求卓越的心,我不能一次就寫出很完美的代碼,但我相信,踏踏實實一步一步的最佳化,代碼就可以變得趨近完美,至少在某一個特定情境下相對完美,這和做人有很類似的道理,這是一種態度。前幾天,發了我在部落格園的第一篇編碼實踐《C#編程實踐–幫老婆計算產假方案》(簡稱前文),引來了幾位博友(這其中還有幾位是以前一起共事幾年的同學和同事,感慨大家在技術道路上的堅持和不易)的圍觀,他們好心點個贊我表示很感激,當然他們也提出了建議,對於這些建議我也不打算置之不理,所以又有了此文。
複雜 or 簡單?
複雜和簡單,在某些時候是個相對的概念。前文中,部分朋友提出My Code有些複雜。我本著謙虛的態度來進行分析,我必須承認,我寫的代碼有過度設計之嫌,違反了K.I.S.S原則。我的工作經驗導致我常常以中大型項目的思維方式去寫代碼,會考慮物件導向的設計,考慮架構系統的一些指標以及規範(高可用性、穩定性、可讀性、可維護性、可擴充性、可測試性等等),所以有些朋友說My Code過於複雜,我想我可以比較簡潔的去概況我的思路,讓大家知道我的初衷。
職責:節日的表達和儲存結構
屬性:使用月、日和曆法來表示節日
靜態唯讀欄位:表示不可變的常量,代替魔法變數(Magic Number)
設計參考:參考.net framework BCL的DateTime結構定義
職責:假期的表達和儲存結構
屬性:節日、放假規定(提前幾天放,一共幾天假)
邏輯:將假期轉變為通用的枚舉集合(IEnumerable<DateTime>)
判斷是否假期的規則邏輯,介面如下
1: public static bool IsHoliday(this DateTime date);
2: public static bool IsHoliday(this DateTime date, IEnumerable<Holiday> holidays);
至此,我想,大家認為所謂的複雜,在於兩點:
- 資料的儲存和表示,“我去翻翻日曆,用一個集合來儲存所有假期日期不就完了嘛!”
- 邏輯的關聯依賴,IsHoliday的邏輯使用擴充方法表示並與Holidays依賴,其實這裡可以進行一定的最佳化,比如:
1: public static bool IsHoliday(this DateTime date, Func<DateTime,Boolean> holidayCondition);
使用委託,此處參考IEnumerable<T>的LINQ擴充方法設計,依賴於委託,讓調用者實現具體邏輯
最佳化
我在前文中提到,LINQ查詢可以進行一定的最佳化,我那個查詢顯然很糟糕,要知道從一個時間段裡選出98天的間隔需要兩次迭代嗎?天哪,記起來了嗎?這就是笛卡爾積的數量級啊,我們完全沒必要進行SelectMany操作啊對不對,使用一次迭代就可以搞定的查詢幹嘛要用兩次查詢呢?對不對,以下是最佳化過的LINQ查詢:
1: var begin = new DateTime(2014, 1, 1);
2: var end = new DateTime(2015, 12, 31);
3: var sample = DateUtility.RangeDay(begin, end);
4:
5: var solutions =
6: from iterator in sample
7: let last = iterator.AddDays(days - 1)
8: let range = DateUtility.RangeDay(iterator, last)
9: where last <= end
10: select new
11: {
12: Begin = iterator,
13: End = last,
14: HolidayCount = range.Count(d => d.IsHoliday())
15: };
16:
17: var local = solutions.ToList();
結語
寫代碼很簡單,寫出優質代碼則很難。本來還想再寫一個簡化版的(因為大家都覺得過於複雜),但時間有限,先到這裡了!
C#編程實踐–產假方案最佳化版