2015年7月17日 星期五

物件導向實作課程Day2 筆記

簡單記錄一下第二次上課內容大項目如下:

  1. 建構式
  2. 靜態類別、成員
  3. 擴充方法
  4. 介面
  5. 泛型
  6. Lambda簡介與原理
  7. 迭代器
  8. 索引子
  9. 類別設計

自己平常寫程式真的不會把建構式當一回事,也沒想到有那麼多學問,真的是上了一堂震撼教育課。大概就是繼承鏈那一段執行步驟搞清楚後,才會有豁然開朗的感覺。舉例如下(執行步驟用註解方式呈現):

   1: public class InheritChain1
   2:     {
   3:         //Step2
   4:         protected int width;
   5:         
   6:         public InheritChain1()
   7:         {
   8:             //Step3
   9:             width = 10;
  10:         }
  11:     }
  12:  
  13:     public class InheritChain2 : InheritChain1
  14:     {
  15:         //Step1
  16:         protected int height;
  17:         public InheritChain2()
  18:             : base()
  19:         {
  20:             //Step4
  21:             height = 20;
  22:         }
  23:     }

其他的不多說,紀錄於「心智圖」中,此次上課用到的相關範例都會紀錄上去,因為自己在整理筆記時發現,會忘記哪一個單元用了哪一個範例程式;花了兩天時間,但目前整理到「泛型」單元,為擴充Day1筆記中的「心智圖」。心智圖如下:


物件導向


註:Evernote筆記上有附件,若要觀看請下載xmind


參考:SKILLTREE物件導向實作課程(第四梯)

2015年6月20日 星期六

物件導向實作課程Day1筆記

今年八月出社會將滿四年,一直都是寫程式為業的我來說,不該是程式寫完、寫好就足夠,該是思索並追求重構,具備擴充性、可測試性,以及設計模式運用等等的時候了。

出社會後的第一份工作,就是寫C#,且因為在校時使用VB的關係,上班第一二個禮拜都在看C#書籍中渡過;說到這,根本就被Bill叔說中,當時看的書就是那種教你怎麼用VS介面拉出Button,寫事件等等快速開發,但卻沒講到背後的真正操作意義。而上這堂課完全就是被課程簡介吸引過去的:

不要再迷信「設計模式」的課程,應該先從基礎的「物件導向」學起,融會貫通以後你會發現,設計模式不再困難!因為觀念通了,一切就通了

想想前幾個月買的「大話設計模式」才翻到第三章就沒在動了,於是乎,決定要報名SkillTree物件導向實作課程第四梯的課程了。

Bill叔講得很熱血,也講得淺顯易懂,配合實例的介紹,印象頗為深刻。上個月「TDD課程」的課後劃心智圖筆記後,整個上癮了,決定這次在課堂上同步劃心智圖的目標,但徹底宣告失敗,在思考觀念後要動鍵盤時,講師已經往下個議題了,下禮拜還是備紙跟筆,以防萬一。

課程一開始從物件導向的三大特性:繼承、封裝、多型講起,此時提到「設計模式」是組合運用這三大特性,我心想我來對地方了。當然你要組合運用前,勢必得從最基礎知識建立起,接著介紹型別及變數的單元,之後是包含超多東西的類別Class的介紹。

下課後一個晚上整理了一下,不免俗地來一下心智圖吧,心智圖如下。

物件導向

Bill叔在課堂中,用白板筆畫圖解釋,就是Call by value及Call by reference單元。一個是傳值,意思就是複製一份變數給該方法;另一個是傳址,表示只是傳給該方法的是變數的指標(變數所在地址)。簡單分別就是在該方法中若有任何對該變數任何更動情況下;Call by value是不會有任何影響的,因為已經是複製一個新的變數給該方法,任何更動與原本的變數無關。反則Call by Reference來說,會更動到原本變數的值。所以Bill叔一直在強調不要管「實質型別」或「參考型別」,而是變數本身。參考一下MSDN的範例就知道了,實質型別傳遞參考型別傳遞。Bill叔建議不懂或無法理解的就用紙筆,劃出圖出來,我怕我在紙上劃的,會傷到大家的眼睛,因此使用Visio重新劃了一下。實質型別傳遞如下:

CallByValueByReference_實質型別

參考型別傳遞如下:

CallByValueByReference_參考型別

再來寫一下範例程式會更有感覺,我稍稍更動了一下Bill叔的範例,如下:

   1: public class TestClass
   2: {
   3:     public int x = 0;
   4: }
   5: static void Main(string[] args)
   6: {
   7:     TestClass y = new TestClass();
   8:     y.x = 1;
   9:     TestClass r1 = ChangeByVal(y);
  10:     Console.WriteLine("y原本的值 : " + y.x + "; y更動後的值: " + r1.x );
  11:     TestClass r2 = ChangeByRef(ref y);
  12:     Console.WriteLine("y原本的值 : " + y.x + "; y更動後的值: " + r1.x);
  13:     Console.ReadLine();
  14: }
  15:  
  16: private static TestClass ChangeByVal(TestClass y)
  17: {
  18:     y = new TestClass();
  19:     y.x = 2;
  20:     return y;
  21: }
  22:  
  23: private static TestClass ChangeByRef(ref TestClass y)
  24: {
  25:     y = new TestClass();
  26:     y.x = 2;
  27:     return y;
  28: }

執行後的結果:


image


就是使用Call by reference(第二種),連原本的值也會被更動到,因為指向同一個物件。


這堂課,對我印象深刻的是,委派部分,說真的因為之前工作的關係,會用到多執行緒的部份,然而常常有一些結果需要回饋到UI介面上,若直接在多執行緒的程式中直接更動UI時一定會報Error出來的。於是你會查網路,都會查到使用委派的方式解決,所以網路上的解釋就是因為更動UI不是該執行緒的工作,而是主執行緒的工作,因此需要委託主執行緒來執行。Bill叔的簡單解釋,委派就是方法外部實作,聽到這,讓我想到Interface,它不是也在Interface Class中只是宣告方法的殼,繼承的Class去實作它,不是也跟委派一樣是方法外部實作。因此查了一下發現網路是很多文章討論這兩個的差異,連MSDN上也可找到,參考:Interfaces Vs DelegatesWhen to use delegates instead of interfaces,再來找時間好好研究Bill叔的委派一系列文章。講到這,大致是可以了解其中的分別,或許實作時會更有感覺吧,先寫到這吧,寫了好久,若有甚麼新的資訊或實作範例再更新上來。


註:Evernote筆記上有附件,若要觀看請下載xmind

2015年6月6日 星期六

筆記-自動測試與TDD實務開發Day1

認識91大是從「進入IT產業必讀的200個.net面試決勝題」,這本書在低潮轉職時陪伴我許久。這本書買回家時,看作者跟譯者經歷,才知91是大我六屆的學長,想想學長的發展,真覺得慚愧,覺得該是奮發向上的時候了。又面試下來的感覺,真正在乎技術的公司,皆看重unit test與設計模式,在這時看到skilltree網站上91大的TDD課程訊息,二話不說就報名了。

課程部分超充實又實用,讓我覺得好好努力地寫測試下去,總有一天機會會來臨的。91大的課程安排,非常用心,每一次的講課、實作練習、分組搶答及主題結束後的Recap等等在課程內容吸收上的幫助大大的提升。小弟不才,看到上課同學寫的精彩筆記,只好採取有別於一般文字紀錄筆記方式,複習投影片內容同時,花時間畫了心智圖,參考如下:

https://www.evernote.com/shard/s166/sh/f07f3df2-96a6-4271-a5b7-022dc863e878/fca9559fca739d10ac3546ea7aea8ef2

Unit Test

總的來說,上完課程後,91大的一句話深深烙印在我腦海中,「不要用想像的,寫測試來驗證你的程式吧」,正好這次的Case還在系統分析階段,期許自己到開發階段時希望能發揮課堂所學。

註:筆記中的心智圖可以搭配最近迷上的軟體xmind

2013年12月10日 星期二

繁簡轉換Function(C#)

最近有需求是若前面輸入的字串為簡體編碼則先轉換成繁體至資料庫查詢,最後結果呈現上,查出的資料庫裡的繁體資料須置換成簡體後秀出。

我找到一個很不錯的一個範例網站:http://jian-zhoung.blogspot.tw/2012/07/c.html

上述範例網站,介紹到四種方式繁簡轉換,我以這四種為例寫成一個Class檔,其他頁面統一呼叫此Class來達成。

第一步:加入一個名為「LanguageTool.cs」Class。

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5: using System.Text;
   6:  
   7: namespace UDP2013
   8: {
   9:     public class LanguageTool
  10:     {
  11:  
  12:         public LanguageTool()
  13:         { 
  14:         
  15:         }
  16:     }
  17: }

第二步:加入一個判斷是否為簡體編碼的程式,名為「IsGBCode」,傳入變數為欲判斷的字串,回傳bool變數。Function如下:



   1: /// <summary>
   2: /// 判斷是否為GB2312編碼
   3: /// </summary>
   4: /// <param name="word"></param>
   5: /// <returns></returns>
   6: public bool IsGBCode(string word)
   7: {
   8:     byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(word);
   9:     // if there is only one byte, it is ASCII code or other code
  10:     if (bytes.Length <= 1)
  11:     {
  12:         return false;
  13:     }
  14:     else
  15:     {
  16:         byte byte1 = bytes[0];
  17:         byte byte2 = bytes[1];
  18:         //判斷是否是GB2312
  19:         if (byte1 >= 176 && byte1 <= 247 && byte2 >= 160 && byte2 <= 254)
  20:         {
  21:             return true;
  22:         }
  23:         else
  24:         {
  25:             return false;
  26:         }
  27:     }
  28: }

第三步:加入繁簡體轉換Function,四種方式皆一步一步列出,如下:


**Kernel32 LCMapString**


須先加入「System.Runtime.InteropServices」參考。



   1: using System.Runtime.InteropServices;

相關Function如下:



   1: #region ---使用Kernel32 LCMapString轉換---
   2:  
   3:  internal const int LOCALE_SYSTEM_DEFAULT = 0x0800;
   4:  internal const int LCMAP_SIMPLIFIED_CHINESE = 0x02000000;
   5:  internal const int LCMAP_TRADITIONAL_CHINESE = 0x04000000;
   6:  
   7:  [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
   8:  internal static extern int LCMapString(int Locale, int dwMapFlags, string lpSrcStr, int cchSrc, [Out] string lpDestStr, int cchDest);
   9:  
  10:  public string ToSimplified(string source)
  11:  {
  12:      String target = new String(' ', source.Length);
  13:      int ret = LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_SIMPLIFIED_CHINESE, source, source.Length, target, source.Length);
  14:      return target;
  15:  }
  16:  
  17:  public string ToTraditional(string source)
  18:  {
  19:      String target = new String(' ', source.Length);
  20:      int ret = LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_TRADITIONAL_CHINESE, source, source.Length, target, source.Length);
  21:      return target;
  22:  }
  23:  
  24:  #endregion

**Microsoft.Office.Interop.Word**


先在專案檔案中引用Com元件:Microsoft Word 14.0 Object Library。


AddMSWord


接著在程式檔案中加入「Microsoft.Office.Interop.Word」參考。



   1: using Microsoft.Office.Interop.Word;

最後附上Function,如下:



   1: /// <summary>
   2: /// 使用Microsoft.Office.Interop.Word轉換
   3: /// </summary>
   4: /// <param name="argSource"></param>
   5: /// <param name="argIsCht"></param>
   6: /// <returns></returns>
   7: public string ConvertUsingWord(string argSource, bool argIsCht)
   8: {
   9:  
  10:     var doc = new Document();
  11:     doc.Content.Text = argSource;
  12:     doc.Content.TCSCConverter(
  13:         argIsCht
  14:             ? WdTCSCConverterDirection.wdTCSCConverterDirectionTCSC
  15:             : WdTCSCConverterDirection.wdTCSCConverterDirectionSCTC, true, true);
  16:  
  17:     var ret = doc.Content.Text;
  18:     object saveChanges = false;
  19:     object originalFormat = Missing.Value;
  20:     object routeDocument = Missing.Value;
  21:     doc.Close(ref saveChanges, ref originalFormat, ref routeDocument);
  22:  
  23:     return ret;
  24: }

**Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter**


要先在網路上下載「ChineseConverter.dll」、「ChnCharInfo.dll」參考至專案中。接著再程式檔案中加入參考。



   1: using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
   2: using Microsoft.International.Converters.PinYinConverter;

**Microsoft.VisualBasic**


首先需引用「MicrosoftVisualBasic」元件,如下。


AddMSVB


接著在程式檔案中加入參考,如下:



   1: using Microsoft.VisualBasic;

最後附上方法程式碼的部分,如下:



   1: /// <summary>
   2: /// 使用Microsoft.VisualBasic轉換
   3: /// </summary>
   4: /// <param name="argSource"></param>
   5: /// <param name="IsTraditional"></param>
   6: /// <returns></returns>
   7: public string ConvertUsingVB(string argSource, bool IsTraditional)
   8: {
   9:     string Rtnstr = "";
  10:     switch (IsTraditional)
  11:     {
  12:         case true://表示要轉換成繁體
  13:             //zh-TW (0x0404), zh-CN (0x0840), ko-KR (0x0412), en (0x0009)
  14:             Rtnstr = Strings.StrConv(argSource, VbStrConv.TraditionalChinese, 0x0404);
  15:             break;
  16:         case false://表示要轉換成簡體
  17:             //zh-TW (0x0404), zh-CN (0x0840), ko-KR (0x0412), en (0x0009)
  18:             Rtnstr = Strings.StrConv(argSource, VbStrConv.SimplifiedChinese, 0x0404);
  19:             break;
  20:     }
  21:  
  22:     return Rtnstr;
  23: }

使用方法(以第三種ChineseConverter為例):



   1: LanguageTool LanTool = new LanguageTool();
   2: string TBoxTxt = curTextBox.Text.Trim();
   3: if(LanTool.IsGBCode(curTextBox.Text.Trim()))
   4: {
   5:     TBoxTxt = LanTool.ConvertUsingCConverter(TBoxTxt,true);
   6: }

上面方法先宣告LanguageTool的物件,接著使用此物件判斷是否為簡體編碼,若是則進入判斷式中將字串轉為繁體。若轉為簡體則相反,將第二個參數設為false即可。


最後附上原始碼檔案連結


https://drive.google.com/file/d/0ByqUJS6xlP4xNkNIb3htOWdFOU0/edit?usp=sharing