2013年9月30日 星期一

Metro App Property 紀錄

 循環item

<ItemsPanelTemplate>
     <CarouselPanel>
</ItemsPanelTemplate>

讓ScrollViewer一次只能滑動一個item

<ScrollViewer   HorizontalSnapPointsType="MandatorySingle"/>

Get Xaml Template

.xaml
<Style>
...
<TextBlock x:Name="TB"/>
</Style>

.cs
override void OnApplyTemplate()
{
     TextBlock _TB = (TextBlock)this.GetTemplateChild("TB");
}


"CallerMemberName"
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = this.PropertyChanged;
            if (eventHandler != null)
            {
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
            }
        }


使ITEM不會re-load
ItemsPanel裡的 ItemsPanelTemplate -> VirtualizingStackPanel -> CleanUpVirtualizedItemEvent

2013年9月25日 星期三

設計模式 (四) Composite Pattern

通常會用到composite pattern都是在資料為樹狀圖時才會用到它
他的做法是將聚合元素(枝)與單一元素(葉) 視為同一個東西 (繼承同一個物件)
這樣的好處是當新增其他的葉時並不需要修改其他的class
先示範較不好的範例
他的缺點是當有新的葉class要做新增時例如希望新增 BCounty的時候對於bnation來說需要做大量的修改才能順利加BCounty加入
     
    class BRoot
    {
        private string name;
        private List<bnation> Nations = new List<bnation>();
        public BRoot(string name)
        {
            this.name = name;
        }
        public void Add(BNation b)
        {
            Nations.Add(b);
        }

        public void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
            foreach (var Nation in Nations)
            {
                Nation.Display(depth + 3);
            }
        }

    }
    class BNation
    {
        private string name;
        private List<bcity> Cities = new List<bcity>();
        public BNation(string name)
        {
            this.name = name;
        }

        public void Add(BCity b)
        {
            Cities.Add(b);
        }

        public void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
            foreach (var city in Cities)
            {
                city.Display(depth + 3);
            }
        }
    }
    class BCity
    {
        private string name;
        public BCity(string name)
        {
            this.name = name;
        }
        public void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + " city " + name);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            BRoot root = new BRoot("Root");
            BNation BChina = new BNation("China");
            BNation BTaiwan = new BNation("Taiwan");
            
            BChina.Add(new BCity("Ba Jin"));
            BChina.Add(new BCity("Su Jou"));                       
            BTaiwan.Add(new BCity("Taipei"));
            BTaiwan.Add(new BCity("Tainan"));

            root.Add(BChina);
            root.Add(BTaiwan);
            root.Display(0);

            Console.WriteLine();
        }
   }
Result:
Root
---China
------ city Ba Jin
------ city Su Jou
---Taiwan
------ city Taipei
------ city Tainan

正確的範例如下
當需要增加BCounty的時候  就如同增加BCity一樣 新增一個class就可以完成
新的修改並不會對舊有的code造成修改
    
    abstract class Component
    {
        protected string name;

        // Constructor
        public Component(string name)
        {
            this.name = name;
        }

        public abstract void Add(Component c);
        public abstract void Remove(Component c);
        public abstract void Display(int depth);
    }
    class Nation : Component
    {
        private List<component> Nations = new List<component>();
        public Nation(string name)
            : base(name)
        {
        }

        public override void Add(Component c)
        {
            Nations.Add(c);
        }

        public override void Remove(Component c)
        {
            throw new NotImplementedException();
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
            foreach (Component City in Nations)
            {
                City.Display(depth + 3);
            }
        }
    }
    class City : Component
    {
        public City(string name)
            : base(name)
        {
        }

        public override void Add(Component c)
        {
            throw new NotImplementedException();
        }

        public override void Remove(Component c)
        {
            throw new NotImplementedException();
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + " city " + name);
            //throw new NotImplementedException();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Nation Root = new Nation("Root");
            Nation China = new Nation("China");
            Nation Taiwan = new Nation("Taiwan");
            
            China.Add(new City("Ba Jin"));
            China.Add(new City("Su Jou"));
            Taiwan.Add(new City("Taipei"));
            Taiwan.Add(new City("Tainan"));

            Root.Add(Taiwan);
            Root.Add(China);
            Root.Display(0);
        }
     }
Result:
Root
---Taiwan
------ city Taipei
------ city Tainan
---China
------ city Ba Jin
------ city Su Jou

[MerMer] TechDays 2 2013

今天聽了Ruddy 大師的Scrum的教學 還有另一堂 Xamarin 跨平台 app的教學

關於scrum是敏捷軟體開發方法
敏捷開發其實是個蠻特別的開發模式
讓團隊可以提升開發的效率   而且讓產品有韌性(產品可以隨著需求改變)
關於developer能做到的有
pair program
TDD (unit test)
design pattern
Refactoring
恩....聽了這堂課其實心中有蠻多迴響的
希望有朝一日也能成為scrum開發團隊的一份子!!


關於敏捷開發的相關書籍
煙硝中的scrum 和XP
Succeeding with Aglie
Practices of an Aglie developer

關於 Xamarin 是 跨平台的app 語言
意思是用一種語言就可以寫出 ios android win app 3 in 1 的 app
功能看起來頗齊全的
除了拉UI  目前的版本還需要用原本的方式(ios:Xcode  android:eclipse )產生之外
(聽說下一個版本才支援直接在visual裡拉)
其他的功能都可以使用C#去完成 (幫助公司cost down!?)
雖然說是同一個語言但是詳細的寫法在各個版本還是有些差異
例如 listview 在 android 需要用一個adapter class然後實踐 getView
然而在 ios 的話就變成實踐 getCell
好處是 如果有一些演算法或功能的實做只需要寫一份就好了
主管表示: 太好了以後 app 維護只需要1/3的人力 (疑?)

[MerMer]TechDays 2013

今天難得有機會去參加微軟的Tech大會
基本上獲益蠻多的

第一堂是  現代化的軟體生命周期管理
其實重點應該就式介紹 Team Foundation Server的強大
主要印象比較深刻的是能結合GIT 來做版控
還有 Code Map 以樹狀圖顯示  讓 Developer 可以知道哪些function被執行過


第二堂是  專業程式開發者應該有的軟體測試技巧
基本上這堂講的都是 TDD(test driven development)的概念
講了很多visual 2013上的測試技巧
包含windows app 的 unit test  UI test
還有fake object的簡介
比較可惜的是 Fake這部分沒有做更詳細的說明... 只舉了一個daetime設定的例子
(我好想多看一點範例阿)

第三堂是  前端工程-軟體工業的契石
講師叫 蔣定宇是個非常熱血的人
害我這個對html javascript 沒寫過幾次的人也對 front-end engineer 產生了興趣
不過重點不在於哪個行業~
重點在於他說的一句話    詳細的我忘了  大意大概是
努力變強吧  朝著自己的目標前進  有時候機會就會莫名的找上你
其實這才是這整篇文章的重點 XD


2013年9月23日 星期一

OOAD原則 (一) Open/Close Principle 開閉原則

簡稱OCP 意思是

一個軟體應該要夠開放使得他可以被擴充,但是也要夠封閉以避免不必要的修改 

這句話其實很像是繞口令而且看起來很矛盾


讓我們舉個例子
當我們有 功能/Bug 需要去修改程式時 
最好的方法是甚麼?  在程式裡面加上一個flag? 
這個是我覺得最可怕的解法...

每當遇到一個 新功能/Bug 就用flag去判斷
在一開始可以得到不錯的效果
但是當過了一個禮拜....兩個禮拜....兩個月之後
當某天必須回來看這份code  你會發現Long time ago......
(一個好的故事都是這麼開始的....可惜這是一個可怕的code....)
那麼多個flag到底是要幹嘛的
而且一大堆flag 你能很確定的說  這個flag的運作方式就跟當初想的時候一樣嗎?

我記憶力一向不太好  就算有註解   過了那麼久我也還是得把code重新看一次(崩潰...)

所以為了能修改程式又不要動到其他看似沒有問題的程式最好的辦法就是用class去分開他
在不同的情況下使用不同的class去處理事情
Strategy Pattern 就是用到了這個方法 
好處是user只需要知道做了sort這個動作而不需要知道細節
有新功能被增加時並不會影響到main function  (因為加在class裡)

設計模式 (三) Abstract Factory

觀察 main function 可得知
使用者不需要關心 他所創造的是哪個OEM工廠
他只需要知道他目前需要製造的東西是甚麼
好處是 如果使用者之後需要新增OEM工廠
只需要再新增一個class就好
而不需要把code寫在main裡面造成維護或讀code上面的困難
下面的範圍實做兩個OEM工廠
兩個OEM工廠都可以製作手機以及電話


  
    
    abstract class IPhoneBase
    {
        public abstract void Dial();
    }

    abstract class INoteBook
    {
        public abstract void PowerOn();
    }

    interface IFactory
    {
        IPhoneBase CreatePhone();
        INoteBook CreateNoteBook();
    }

    class SamsugPhone : IPhoneBase
    {
        public override void Dial()
        {
            Console.WriteLine("Samsug Phone Is Dialing");
        } 
    }

    class AsuPhone : IPhoneBase
    {
        public override void Dial()
        {
            Console.WriteLine("Asu Phone Is Dialing");
        }
    }

    class SamsugNotBook : INoteBook
    {
        public override void PowerOn()
        {
            Console.WriteLine("Samsug NoteBook Is PowerOn");
        }
    }

    class AsuNotBook : INoteBook
    {
        public override void PowerOn()
        {
            Console.WriteLine("Asu NoteBook Is PowerOn");
        }
    }

    class AsuFactory : IFactory
    {
        public IPhoneBase CreatePhone()
        {
            return new AsuPhone();
        }
        public INoteBook CreateNoteBook()
        {
            return new AsuNotBook();
        }
    }

    class SamsugFactory : IFactory
    {
        public IPhoneBase CreatePhone()
        {
            return new SamsugPhone();
        }
        public INoteBook CreateNoteBook()
        {
            return new SamsugNotBook();
        }
    }

    class OEMFactory
    {
        public IFactory GetFactory(string name)
        {
            if (name == "Samsug")
            {
                return new SamsugFactory();
            }
            else if (name == "Asu")
            {
                return new AsuFactory();
            }
            else
                return null;
        }
    }



    class Program
    {
        static void Main(string[] args)
        {
            OEMFactory Factory = new OEMFactory();
            IFactory AsuFactory = Factory.GetFactory("Asu");
            AsuFactory.CreatePhone().Dial();
            AsuFactory.CreateNoteBook().PowerOn();

            IFactory SamsungFactory = Factory.GetFactory("Samsug");
            SamsugFactory.CreatePhone().Dial();
            SamsugFactory.CreateNoteBook().PowerOn();
            Console.ReadKey();
        }
    }
優點
1.產品從代碼中被分離出來
2.容易改變產品的系列
3.可拿到建立OEM系列的產品族的接口
缺點
1.當要新增OEM工廠裡的產品時須對所有的 OEM class 做修改

2013年9月22日 星期日

設計模式 (二) Strategy Pattern

策略模式 讓使用者可以動態改變演算法
這樣的寫法是使用合成方式 而不是使用繼承來完成我們需要的功能
這樣的好處是彈性較大  假設之後需要針對我們現在的寫法做(需求)
變更  我們並不需要針對舊有的程式做更改  只需要新增一個class就可以了
這是多麼開心的事情  新增功能又不會影響到舊有的功能


接著講sample
假設我今天有一段程式在不同的情境需要套用不同的sort 演算法
就可以套用strategy pattern
代碼如下

C#

    abstract class Sorting
    {
        abstract public void Process();
    }
    class QuickSort : Sorting
    {
        public override void Process()
        {
            System.Diagnostics.Debug.Write("QickSort Algorithm");
        }
    }
    class MergeSort : Sorting
    {
        public override void Process()
        {
            System.Diagnostics.Debug.Write("MergeSort Algorithm");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Sorting sortalgorithm = new QuickSort();
            sortalgorithm.Process();
            sortalgorithm = new MergeSort();
            sortalgorithm.Process();
        }
    }

Java

abstract class Sorting
{
    abstract public void Process();
}
class QuickSort extends Sorting
{
    public void Process()
    {
     System.out.println("QuickSort");
        
    }
}
class MergeSort extends Sorting
{
    public void Process()
    {
     System.out.println("MergeSort");
    }
}

public class strategy {

 /**
  * @param args
  */


 public static void main(String[] args) {
  // TODO Auto-generated method stub
        Sorting sortalgorithm = new QuickSort();
        sortalgorithm.Process();
        sortalgorithm = new MergeSort();
        sortalgorithm.Process();
 }

}

總結  寫code前多想一下吧
多用合成  少用繼承  未來maintain的生活會變得更美好 XD

設計模式 (一) Singleton

Singleton Pattern 就是獨體模式,當需要建立獨一無二的物件時可以使用
以下是範例

C#

    class LoginObj
    {
        private static LoginObj loginobj;
        private LoginObj()
        { }
        public static LoginObj GetInstance()
        {
            if (loginobj == null)
            {
                loginobj = new LoginObj();
            }
            return loginobj;
        }
        public void SetLoginData()
        {
            System.Diagnostics.Debug.Write("Set data");
        }
        public  void GetLoginData()
        {
            System.Diagnostics.Debug.Write("Get data");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            LoginObj loginobj = LoginObj.GetInstance();
            loginobj.SetLoginData();
            loginobj.GetLoginData();
        }
    }

Java

 
public class loginObj {

 /**
  * @param args
  */
 private static loginObj _loginObj;
 private loginObj(){}
 public static loginObj GetInstance()
 {
  if(_loginObj==null)
  {
   _loginObj = new loginObj();  
  }
  return _loginObj;
 }

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  loginObj loginobj = loginObj.GetInstance();
  
 }

}
上面使用singleton建立唯一的物件來存取以及讀取user login的資料 上面的用法是不考慮multi-thread時的寫法 當該class 會同時被多個thread呼叫時使用上面的寫法還是有可能會Create出兩個物件 所以必須改用以下的寫法

C#

       class LoginObj
    {
        private static LoginObj loginobj;
        private static object syncObj = new Object();
        private LoginObj()
        { }
        public static LoginObj GetInstance()
        {
            if (loginobj == null)
            {
                lock (syncObj)
                {
                    if (loginobj == null)
                    {
                        loginobj = new LoginObj();
                    }
                }
            }
            return loginobj;
        }
        public void SetLoginData()
        {
            System.Diagnostics.Debug.Write("Set data");
        }
        public  void GetLoginData()
        {
            System.Diagnostics.Debug.Write("Get data");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            LoginObj loginobj = LoginObj.GetInstance();
            loginobj.SetLoginData();
            loginobj.GetLoginData();
        }
    }

Java

 
public class loginObj {

 /**
  * @param args
  */
 private static loginObj _loginObj;
 private loginObj(){}
 public static loginObj GetInstance()
 {
  if(_loginObj==null)
  {        
      synchronized(loginObj.class){
         if(_loginObj == null) {                
            _loginObj = new loginObj();  
         }
      }
   
  }
  return _loginObj;
 }

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  loginObj loginobj = loginObj.GetInstance();
  
 }

}
通常會用到singleton的時機為
1.想要一個global物件可以做資料存取
2.當使用了某些只能被init一次的API
3.當必須確保該物件為唯一
Reference : 深入淺出設計模式