2013年12月29日 星期日

在Windows Phone (WP8) 中使用SignalR

ASP.NET SignalR【幾乎】讓我想丟掉Push Notification,你就知道它把訊息傳遞這件事情弄得有多簡單方便了。在這一篇我說明一下如何在WP8中使用ASP.NET SignalR,同時也稍微解釋一下這兩天寫的Code。

請回憶一下我們昨天的情境:


我們在伺服器端透過ASP.NET以SignalR寫了一組服務,主要是用來做聊天室(基本上是範例啦)的功能,包含了接收用戶端傳來的訊息(姓名、聊天文字),以及把訊息主動推送給用戶端(姓名、聊天文字),這樣的功能。

而用戶端就很單純的呼叫或傾聽這個服務。呼叫Send方法可以把用戶端使用者想要說的訊息傳給伺服器端,而伺服器端收到,則執行broadcastMessage這個動態方法,把訊息推送給所有傾聽的用戶端。

透過ASP.NET SignalR要寫這個服務端的機制,很簡單。

首先,建立一個Empty WebForm專案(當然你用MVC也行,之所以用WebForm,原因在這裡),接著透過NuGet引用ASP.NET SignalR:


然後在專案中Add New Item,請找到Hub Class(VS2012 Update 4或VS2013):

建立出來的Class如下:
    public class MyHub1 : Hub
    {
        public void Hello()
        {
            Clients.All.hello();
        }
    }

該類別繼承自Hub,這個Hub就是SignalR服務的Bass Class,你可以在其中建立自己的Method,如上圖中的Hello。

我們修改此類別,建立一個聊天室中,接收用戶端傳來訊息的Method,名稱為Send, 其程式碼如下:
    
  public class MyHub1 : Hub //SignalR主要部分
    {
        public void Send(string name, string message)    //接收傳送來的訊息
         {
            //傳送訊息到用戶端            
            Clients.All.broadcastMessage(name, message);  //廣播訊息 (這邊用到了動態方法)
        }
    }

注意上面的Method Send,是用來讓Client端(WPF or WP8)呼叫的,用來把用戶端輸入的聊天訊息傳送到伺服器端,所以有兩個參數 name 和 message。而broadcastMessage也是我們自己定義的Method,用來把訊息傳遞到用戶端。

不過,很有趣的是,這邊用到了Dynamic Method的概念,這個部分我們過去不常談論,但這機制讓我們可以在程式碼中動態的建立類別的方法和屬性。例如上面這個broadcastMessage,本來Clients.All.底下根本沒這個Method,這是我們自己在Visual Studio寫程式時候直接加進去的,參數也是我們當下自己決定的。也因此,這部分Visual Studio是無法幫我們檢查是否有拼字或語法錯誤,你得要自己留意。

透過Clients.All.類別,可以讓我們把特定的資訊推送給用戶端(只要用戶端有設定好connection並傾聽),所以你看到上面的程式碼,我們在收到某一個用戶端透過呼叫Send方法所傳來的訊息之後,就透過Clients.All.broadcastMessage(用戶名 , 聊天訊息)把該訊息傳給所有用戶端。

這樣,只要任何一個用戶端(WPF or WP8 or Windows Form or ...)把聊天訊息傳到到伺服器端,透過伺服器端的broadcastMessage方法,所有傾聽的用戶端就會收到聊天訊息囉:


伺服器端程式碼的撰寫就是那麼簡單,不過別忘了ASP.NET SignalR必須註冊在Web.Config中,所以你必須撰寫一個Configuration方法:
[assembly: OwinStartup(typeof(WebApplication5.Startup1))]
namespace WebApplication5
{
    public class Startup1 //必須在web.config中註冊
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
            app.MapSignalR();
        }
    }
}

然後得在Web.Config中註冊:
  
    
    
  

這樣該Hub才會運行起來。

以上是伺服器端的部分,那用戶端呢? 我們來看看WP8的用戶端App。坦白說,用戶端可就真的很簡單了,如同前面說的,簡單到我【幾乎】(但其實並沒有)想把Push Notification給丟了。

用戶端(不管是WP8 or WPF  or Windows Form or ...),只需要透過NuGet引用SignalR .NET Client即可:

接著,就可以直接使用伺服器端寫好的服務囉。若想要傳送訊息到伺服器端,程式碼大致如下:
        private void ApplicationBarIconButton_Click(object sender, EventArgs e)
        {
            //從Client端送訊息
            proxy.Invoke("Send", TxbName.Text, TxbMessage.Text);
        }

基本上就是呼叫我們伺服器端寫的Send方法。而其中的Proxy哪來的? 請看底下程式碼:

        HubConnection connection;
        IHubProxy proxy;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            Loaded += MainPage_Loaded;
            // Sample code to localize the ApplicationBar
            //BuildLocalizedApplicationBar();
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            //建立connection, proxy
            connection = new HubConnection("http://signalrtestsite.azurewebsites.net"); //測試位置,請自行建立
            proxy = connection.CreateHubProxy("MyHub1");
            connection.Start();
            //listen broadcastMessage
            proxy.On<string , string>(
               "broadcastMessage", (name, msg) =>
                {
                    //非同步(在非UI執行序中)顯示訊息
                    this.Dispatcher.BeginInvoke(
                         () => { lblShow.Text = "" + name + ":" + msg + "\n" + lblShow.Text; });
                }
            );
        }

我們在Loaded事件中,透過HubConnection來建立伺服器端的連線,跟以前使用Web/WCF Services差不多,請留意CreateHubProxy中的MyHub1,就是先前我們在伺服器端建立的Hub Class Name,在Proxy.On這邊,做了一個註冊傾聽的動作,一旦服務器端有呼叫broadcastMessage把訊息往用戶端傳,我們的WP8 App就會收到,並且執行25,26行中的程式碼。(注意這邊用到了匿名方法、以及非UI執行續的Dispatcher,因為該行為是非同步的)

另外,我特別用asp.net寫一個webform的網頁,示範由伺服器端主動送訊息給用戶端:

其程式碼如下:
        protected void Button1_Click(object sender, EventArgs e)
        {
            //透過GlobalHost使用hub instanc
            var context = GlobalHost.ConnectionManager.GetHubContext();
            //由伺服器端主動發訊息
            context.Clients.All.broadcastMessage("admin", TextBox1.Text + " " + System.DateTime.Now.ToString());
        }


這說明了即便不是從用戶端觸發,伺服器端也可以輕鬆的主動傳送訊息給正在傾聽的用戶端。

就這樣,程式寫完了,範例在這裡

========================================================================
後記:

SignalR 用了OWIN這個 .net 的輕量級小組件,拋棄了龐大的.NET Framework,這其實是很有趣的事情,他再一次的說明了資訊界~天下合久必分分久必合~的道理,以前大家想要一組完整的framework(Java or .NET),覺得寫程式拼拼裝裝的很辛苦。現在又覺得framework太大了,而且有相依性的問題,所以又想要自由一點,自己兜出想要的解決方案。

為何會有這樣的改變呢? 過去不可行的,為何現在可行了??? 我想開發工具越來越便利是其中之一的原因,以前(1999年之前)開發人員在沒有framework的情況下,想要蒐集需要的套件很累,現在有Google、有stackoverflow、有NuGet...事情變簡單了,大家就想要提高自由度了,相形之下,一整套Framework似乎就太龐大了。

前端開發技術也是,以前大家想要total solutions,現在JavaScript Framework喜歡自己兜,服務端開發技術也是,以前想要制定一整套的服務描述和查找方法,所以有Web Services和WSDL,現在大家把這些丟了,然後重來一次,就有了RESTful、Web API、JSON、和SignalR這類的技術整合和應用...

天下合久必分、分久必合,所以我開始收斂地不太敢再說趨勢和所謂的主流,因為....你只要Coding的生涯夠長,會發現所有的開發技術,終將都會改變、只要你能活得夠久,終將目睹某個開發技術的興起與消逝。

2013年12月28日 星期六

在WPF中使用SignalR


假日,在等著接送家人的時間空檔,順便寫了一個最近工作上會用到的範例,不知是Windows Client端的技術用的人越來越少還是如何? WPF的使用情境似乎沒啥網友討論,所以範例寫完之後順便放上GitHub,如果有需要的朋友們可以參考。
 
大概的需求如下圖,基本上非常簡單,用WPF與WP8作為用戶端(WP8的範例我晚一點寫),存取以asp.net SignalR所寫的服務,底下先寫WPF的部份:
 

 
會寫這個,主要的原因是,我們公司有不少先前已經搭建好的ASP.NET WebSite(Web Services),這些個WebSite是以WebForm的方式開發的,而用戶端不僅僅只有browser,還有不少WPF/Windows應用程式。所以雖然打算用SignalR做訊息傳遞,但又不是現在大家比較常見的ASP.NET MVC Site(不過說真的, 其實MVC或WebForm根本沒差)。再加上Client端(consumer)又不是Web,而是WPF(和WP8),所以稍微寫個簡單例子整理一下,好讓公司的開發人員可以接手去做後續的部分。
 
先把寫好的範例放在這裡,有需要的朋友可以參考。
 
背後的需求很常見,過去我們有很多以WPF或是XAML(不管是Silverlight/WP8/Windows 8 App...etc)開發的Application,在沒有導入SignalR之前,如果需要知道伺服器端的狀態或訊息,要嘛就是走web services polling、要麼就是走socket,不然就是用push notification(但只有Windows Phone/Windows 8 App才能享用)。因此,傳統的Windows/WPF應用程式(不知道現在還有多少人在寫?),要透過http方式來接收伺服器端主動推送過來的訊息不是非常容易。(搞polling的效能當然是差到不行,又得自己做些手腳提高效能,挺費力)
 
但SingalR讓開發人員現在不用大腦就可以很輕鬆地解決這個問題。
 
所以我們打算在Windows/WPF/Silverlight應用程式當中快速地加入一些由伺服器端推送訊息到用戶端的功能,因此有了SignalR+WPF的這種需求,也因此有了這個範例。
 
範例中,是一個很簡單的聊天室,然後透過一個(其實你可以Run兩個instance比較好玩)WPF Client,搭配SingalR開發的Services,達成伺服器端與用戶端溝通的效果。
 
除此之外,特別用.aspx做了一個在WebForm中透過GlobalHost來主動傳送訊息到WPF Client端的例子,好讓我們的伺服器端可以主動推送訊息到用戶端。
 
時間的空檔到了,過一兩天有空我會再稍微仔細談談這個範例程式碼的部份。順便,下一個例子就是寫個WP8的用戶端了(我明後天補上)...
 
==========================================================
後記:開發技術的進步,讓原本需要耗費不少時間的功能,現在可以用等人的空檔花一兩個小時就完成 ~ 這很有趣,但也有些令人感慨(因為剛好前幾天聖誕夜分享中,又再次有學員問到,軟體開發技術的改變迅速,是否還值得再多花時間投入云云~ )。


2013年12月6日 星期五

China TechED 2013 北京、上海,順利完成

早上,順利完成了China TechED在北京與上海的場次,本來昨天測試的HDMI投影整片花花的狀況幸好沒再發生。由於China場次只有60min,原先在台北講了近兩個多小時的架構設計,只能挑著重點講,很拚。

不過至少沒有發生嚴重超時的問題,感謝上海與北京的朋友們熱情捧場,在早上第一個場次的時段,依舊給予相當熱情的支持。

課堂中的案例檔案可由此處下載:
http://arock.blob.core.windows.net/blogdata201312/Examples.zip

相關的範例與影片可以參考底下連結:
http://studyhost.blogspot.com/search/label/Enterprise%20Library

後續我會陸續把每一個範例以及China場次的內容更完整的整理後,再在這邊跟大家分享。

2013年10月19日 星期六

專業主義的秘密 - 練習


先前和朋友聊到,最近同時間看一套日劇 Dinner 和 著名的 The Clean Coder  一書,被其中的專業主義感動到不行。

The Clean Coder  剛看完第六章,章名是我從來沒有跟大家分享過,卻是我奉行已久的關鍵字 - 練習。

我絲毫不想透漏Dinner的劇情,以及Robert C. Martin在The Clean Coder ㄧ書中提到關於練習的描述。這些東西(看Dinner這部片以及The Clean Coder這本書)將是屬於你這個月最頂級的享受,我不忍心剝奪它。但我忍不住要說,Dinner男主角在每天下班後忙到深夜的事情、和Robert C. Martin用了一整章說的故事,說到底,都只有簡簡單單卻始終被大家忽略的一個字,練習。

這年頭,很少程式設計師會進行"練習"了,而且是重複的練習。但你絕對沒有意識到,這件是有多麼的重要...老實說,如果不是因為要上課,我自己大概也沒有機會有這麼深的體會。但是,在這邊我要跟大家分享的,就是這近十年來,我擔任教育訓練人員、作者、或是顧問時,一直奉行不渝的 -- 練習。

練習什麽呢? Robert在書裏面有說,像是kata, wasa之類的(這你要看書才知道,說過了,我不想剝奪你的樂趣)。但我想跟大家說我自己的經驗,那就是『研討會前的練習』。

如果你熟悉我,你就會知道我講話的速度應該不算慢,在研討會上,我盡可能在兼顧清楚的情況下,以最快的速度跟大家分享,同時間,每一場次的研討會,我都要求自己,要盡可能地與學員互動。

我們也都知道,大夥兒希望看到Live Demo,也因此,我的每一場研討會,幾乎都會有Live Demo的部分,拿今年TechDay Taiwan 2013的例子來說,架構設計的場次中,我簡單Demo了應用程式的分層開發、Unity Application Block的例子、Logging Application Block的例子。在WP8的場次中,我介紹了動態磚、Lock Screen、NFC、App Communication,其中都不乏Live Coding。

一場研討會的時間是70分鐘,其實講師們都清楚的知道,只要Live Demo當中,有一個環節不正確或出現意外狀況,幾乎就有可能讓整個Session毀掉,你不可能讓台下的學員看你在上面Debug、Try and Error...再Debug,或重開機...。也因此,Live Demo要盡可能的行雲流水,如果是超過兩三個範例,那麼挑戰就會倍增,如果再加上幾個不確定性因素,例如網路連線狀況(速度慢或斷線)、投影機(螢幕解析度)、緊張(不熟悉的場子)、麥克風(沒有領夾式的麥克風,導致只剩一隻手敲鍵盤)...這些都會大大影響整個Live demo的狀況,也因此,要順利成功的進行Live Demo,關鍵因素只有一個,就是大量的練習。

你要不要猜猜看我在每一場大型研討會前,要Live Demo的內容有做過多少次練習? 我要告訴你,每一個範例、每一個動作,絕對都"完全一樣地"重複練習超過三次以上,如果時間夠,我會練習到五次,其中一次會錄影起來,以備不時之需。

同樣Demo一個範例,例如用WP8建立一個iconic tile,我會在有網路、沒有網路的狀況下各練習一次,接著把螢幕切成只有1024x768的時候,再練習一次(因為投影機大多只支援到這個解析度)。練習時寫的Code完全不變,就是換不同的環境,如果時間允許,我會換一台NB(或開一個虛擬機),再練一次。

因為多年的經驗,我們清楚的知道,有網路和沒網路很可能Demo效果和路徑(操作步驟)會完全不同,在1024x768或1280x800的解析度下,滑鼠點選螢幕上的某個視窗,位置可能會不同,這會影響Live Demo的路徑、而路徑會影響速度,甚至會影響你的信心。

因為我們清楚的知道,一旦因為解析度不同、或是網路沒有連線,導致正式上場時Live Demo的路徑(操作步驟)和在家裡操作的不同,講師很容易緊張,ㄧ緊張,就會出錯。

所以我得說,你在現場看到ㄧ次順利的Live Demo,其實往往是講師(至少是我),以完全同樣的步驟在家裡、公司,練習過了三五次之後的結果。先不談準備內容和撰寫範例,光花費在重複練習的時間,已經超過研討會正式上場時間的五倍以上。

但是充分的練習,才能讓我們正式上場的時候不緊張,才能夠在各種環節與情境下,都隨時保持著自信、泰然自若的面對各種可能發生的問題。Live Demo時,打錯一行字,出現ㄧ個Bug,不急,別怕,因為我練習的時候碰到過,不擔心,我知道怎麼解決。

我告訴你我在練習時碰過的幾個極端的例子,包含建立專案的時候不能Build,是因為專案資料夾名名稱+檔案名稱超過Visual Studio的長度限制;用NuGet安裝套件,碰到臨時沒網路忘了要裝那些.dll;開的專案範本不同,套件在.net 4.5才能run,Demo時候卻開到.net 4.0的範本,某些.dll裡面隱含著用了另一個不知名的.dll卻忘了add reference...這種狀況,如果是在台上臨時遇到,我可能直接束手投降,放棄這一段的Demo。但沒有,你幾乎沒看到我們在台上這樣,因為那些問題正式上場時幾乎沒發生過。而沒發生,是因為我知道可能會有這個狀況而先避開了,這些...都是因為事前的練習。

最近這幾年,我習慣把練習的過程順便錄成影片,因為要錄影,所以會有我的旁白,也就是錄影時候的說明,這個說明,事實上又是另一次的練習。我除了在上台前會將Live Demo練習幾次,包含每一張投影片上該講的內容,都會試著整個走過一遍,如此一來就可以知道大概需要多少時間,哪一張投影片需要長一點、哪一張投影片可以稍微帶過即可。而練習時Live Demo的錄影,也可以讓我預先練習現場要跟學員怎麼說明和介紹這段程式碼,因此我幾乎在比較大型的研討會,都會事先把影片錄好的原因,錄影的過程,也是一種練習。

如此一來,準備一場研討會,我大概寫了5-10次的動態磚建立、5-10次的Unity Application Block的範例、5-10次的Logging Application Block的範例5-10次的Lock Screen、5-10次的NFC、5-10次的App Communication...

到最後,一場研討會下來,最熟悉整個開發的流程,收穫最多的,其實就是我自己。上課強迫我非得hands-on,而實際下手去做,才是真正"有效的學習"。
===================
後記:
你可能覺得,我又不是講師不多機會上台介紹技術,那還要練習幹嘛? 其實,只要你是ㄧ個程式設計師(甚至是Sale, Presale)、需要跟客戶、老闆、長官 Demo、需要準備驗收的UAT,需要對內部同仁進行技術分享,你的Demo都應該要事前練習,甚至只是看ㄧ本書之後的心得記錄,寫寫blog...這些都是你可以練習的機會,有機會,就不要放過,前面說過,多練習,實際下手去做,才是真正有效的學習。

2013年10月17日 星期四

如果人人都能寫程式???



今天早上看到這一篇文章:
http://share.inside.com.tw/posts/2775
還有以前的一兩篇文章
http://mrjamie.cc/2013/10/17/programming-generation/

讓我忍不住想講一些自己的觀察(感受),當然,從很久以前我就知道我其實是屬於少數人那一掛的,也就是說,當網友們極力反對或贊成某些事情時,我常常不知好歹的站在另一邊。最近我也常常FB一些其他人不太同意的論調...不過慶幸我生在一個還算和諧的時代,我不會因為這樣就被燒死...(因此請大家也別太認真,我的論點絕對有可能是錯的,甚至很多時候,我也曾故意寫過一些些不是那麼精準和正確的內容...)

早上看到的那篇文章,讓我直覺地想到,未來幾年我們很可能會開始活在一個人人都能寫Code的時代。說人人有點誇張,但比例勢必會大幅提升,原因很簡單,你有沒有發現,現在大家都在教別人寫程式??? 而且只要你願意,幾乎可以不用任何成本的學會寫一套程式(大概只需要花點錢買NB、和上網)

最近這十年,Coding這件事情有幾個重大的改變:
  1. 開發人員年齡層與進入門檻持續下降(年輕駭客、或是年輕億萬富翁比比皆是)
  2. 軟體開發資源突然間變多(拜internet普及、全球化資訊自由流通之賜)
  3. 通用軟體價值(實際售價)開始變低(這有個歷程,從30年前硬體收費軟體免費,變成20年前軟體很貴硬體便宜賣,到最近10年又有點變成軟體免費或隨著硬體銷售的趨勢)
  4. 軟體以服務的面貌收費

特別是第四點,很多人覺得似乎沒什麽,ASP或是SaaS都講了很久了,但這十年的改變異常之大,讓人措手不及。

以前獨立開發人員,可以在車庫裡面寫出一個mail收發軟體,然後放上BBS網路銷售,或是讓網友donate這個軟體。但這幾年這樣的模式還是有,但越來越限於特定族群、特定領域的應用程式。才不過五年前,大家搶著寫App賺錢,現在卻又說App不用IAP就賺不了錢!!! 終端消費者(End-User)開始視軟體為免費是理所當然的事情。

過去三十年來所建立的軟體有價的概念,隨著internet on line services普及而開始崩解,現在的終端消費者,越來越覺得軟體應該不能收錢,如果要跟我收錢,那最好你能提供像Google一樣的服務再說,否則程式設計師想收錢? 門都沒有,我用google app就好囉。

軟體開發人員必須知道,軟體免費的時代快來了,如果市場能接受軟體免費而服務收費,其實對於大型企業來說無形中建構出了一道擋住中小企業的進入障礙與門檻。

Google的"服務"有效的(在暗地裡逐漸)改變了軟體消費者的使用習慣以及價值觀。Google甚至改變(加速)了微軟的軟體銷售模式(Ex. Office 365)。

然後,軟體世界就變了。

一直以來,我並不是一個強烈擁護應該將所有資訊與開發技術、技巧100%都放到blog上公開的人。那些標榜著分享、Open...等等的偉大主張,我並不是完全同意與支持。理由很簡單,我壓根不覺得分享是理所當然的事,如果你長時間的分享,你就會發現,除非你覺得分享這件事情本身是個極大的樂趣,否則它真的是一件很辛苦的事情。除此之外,分享的成本很高(而且當你夠老之後,就會發現這個成本還會隨著年紀越來越高),因此沒事不會有人寫個幾百篇blog只是為了一個崇高的理想。

我得說,其實掌握這些知識(資源)的人很多很多,很多人躲在企業裡面,能力不輸講師、作者,只是下班後還希望有更多的家庭生活和自己的時間,因此壓根不想浮上檯面。說真的,其實沒有人生來就應該要分享。blog作者所分享的東西,常常是自己花了十多倍的精神和體力,才得到的一點點經驗,說穿了其實也就不值錢了。但卻能省去其他人花費相同的時間。知識的分享本身真的是很崇高的。

回想,年輕時候的分享真的只是分享,動機很單純,只是因為發現了一些什麽,忍不住想要告訴更多人。但為什麽分享這件事情,年紀越大就越少? 職位越高就越少? 因為隨著年紀,人生的挑戰開始變多,許多人自顧不暇,更罔論持續的分享了...

(有時候分享還會被指指點點,就更令人氣結:再有時候分享完全沒有任何人指指點點,那就更是一種淒涼了...)

所以你看到的分享,要麼就是作者的偉大情操(這種你要感謝),要麼就是背後多多少少有著一些原因或目的,特別是技術從業工作人員的分享(這種你要保持警醒)。

最近十年,整個開發社群、Open Source社群、服務導向的公司,將"軟體開發技術分享"這件事情,形塑成一個很崇高的理想、或是開發人員的使命。有點那種,我share故我在的終極使命感。

但我想換個角度提醒大家,不知道你有沒有發現,分享的單位(或個人)所分享的內容,往往並非自己的核心競爭力,或是核心競爭力的來源。我不方便描述得很明確,我只能說,只有在分享對分享者(個人或企業)本身是無害(甚至有利)的時候,分享這件事情才能長久持續。

所以你慢慢發現,網路上基礎程式設計的分享變多了,開發技巧的分享變多了,特別是在北美成熟穩定的開發人員世界,由於開發人員的普遍薪資比較高(比台灣),所以基礎開發技術的分享俯拾皆是。但這對於活在像台灣這樣的環境的資訊軟體從業人員來說,是好還是不好,是有利還是不利?

比起個人,大公司或大企業,更會清楚的盤算利弊得失,我相信,對於大企業來說,鼓勵開發人員"針對開發技術"來分享,最終絕對是利多於弊。

我挑明了說一句,當基礎開發技術俯拾皆是、唾手可得的時候,事實上最有利的很可能是業主、老闆,因為開發人員的薪資沒有(無法)變高,但開發成本明顯降低了。這對推廣技術(把餅做大)、降低成本絕對是有利的,但這對於基礎開發人員來說,則不見得是全然有利的(所以回頭想想,開發人員不顧自己生計地持續的在分享,這才真真正正的是一個偉大的情操)

當然,這對整體社會來說好不好? 我認為好,因為更多的人受開發相關的教育訓練,對於邏輯和分析能力有相當大的幫助,對整體社會來說我想會是好事。犧牲一部分開發人員的權利,來換取整體社會的進步好不好? 我認為好!(你可以想,因為自私的David不是基礎開發人員,所以根本沒差...恩...是這樣嗎?) 但正在看這篇文章的你呢? 我很想知道你覺得好不好?

總的來說,大量的軟體開發技術分享,將會壓抑軟體開發成本。不過我們本來就在追求更低的軟體開發成本,不是嗎? 每一個開發人員不是應該時時求進步,時時處於學習與戰鬥狀態嗎? 如果你是這麼期許自己的,那真的值得恭喜與驕傲。的確應該如此,這是軟體開發人員的使命。我自己也是這樣期許自己...

軟體開發人員要有志氣(與勇氣)的對自己說:『我們是走在時代前端的開發人員,不是傳統產業,我不擔心工作被搶,我們不怕國際化、全球化的挑戰!!!』

但,如果你想知道為何軟體開發人員薪資似乎越來越低,那我也得誠實的告訴你,在現在這種開發技術隨手可得的時代,如果沒有每天學習,你的薪資就真的是只可能會越來越低。你說有些行業的技術幾十年不變、不需要每天學習,像是會計師、律師就不用啊,不公平!!! 對,答對了,看起來就是這麼的不公平。這會不會根本整個就是大公司或是老闆、業主的陰謀??? 讓大家分享,鼓吹大家分享,然後降低軟體開發成本? 呵呵,我怎麼會知道,你自己覺得呢?

但我最後要說的是,不管有利或不利,這就是一個趨勢。前陣子引用Ruddy老師說過的話,一位信仰敏捷的人,是會認清這個事實:「你無法凍結需求,正如你無法凍結市場、競爭、知識、進化或者成長一樣。」簡單的說,不管你願意不願意,我們就是正邁向一個每個人都能寫Code的世界。 你...擋...不...住...的

如果你不學習,不試著提升自己(這個學習和提升,指的絕對不只是軟體開發這個領域),或許下一波挑戰來臨時,軟體開發人員將面對如同過去傳產從業人員所面對一樣的大規模失業問題...

人生的挑戰,從來沒有消失過。

2013年10月14日 星期一

MS Enterprise Library 6.0 (四) - Policy Injection Application Block

如果說Unity Application Block可以算得上是一份美味的佳餚,那 Policy Injection Application Block 絕對稱得上是開發人員最華麗的盛宴了。

要介紹Policy Injection Application Block之前,得提醒讀者,建議您先熟悉先前介紹過的Exception Handling Application Block以及Logging Application Block,因為我們待會要利用 Policy Injection Application Block 來作一個應用大集合。

首先,請你回憶一下Exception Handling Application Block,以及想像一下Exception Handling Application Block會怎麼用在你的系統中,以及怎麼幫助你以一個單一的例外處理模塊來管理你開發的系統的Exception...

不要偷懶,想像一下...
...
...
...
...
...

好,接著我們回到現實面,你會發現,我們前面說過,可以透過Exception Handling Application Block來管理例外,提供一個統一的方式來處理各種不同可能的例外...這樣很好,我們的系統透過這樣的設計,已經大幅的將耦合性降低,並且提高了重用性,這樣還有什麽讓人不滿意的地方呢?

有的,當程式碼愈趨鬆耦合時,我們開始看try...catch不太順眼。此話怎說??? 請看下面這塊典型的try...catcah:
public void MethodA()
{
    try
    {
        int a = 10, b = 0;
        a = a / b;
    }
    catch (Exception ex)
    {
       //以Config檔案中的 "Policy" ExceptionPolicy設定來處理
       var rethrow = ExceptionPolicy.HandleException(ex, "Policy");
       //如果設定檔說要重丟例外,就重丟
       if (rethrow) throw;
    }
}


有沒有發現,雖然我們簡化了catch當中的程式碼,但是如果我們仔細思索,會發現try...catch這個機制,幾乎會出現在每一個可能發生例外的method當中,也就是說,如果我們寫的嚴謹一點,try...catch幾乎在每一個重要的method當中都會出現。

(我知道你可以在某些開發環境中透過Global的例外處理模塊來處理,例如ASP.NET的Application_Error,但為了解釋方便,請先當作這個機制不存在....)

也就是說,我們的程式碼可能開始會變成這樣
private void MethodA()
{
    try
    {
        //Business Logic block
        //Business Logic block
        //Business Logic block
    }
    catch (Exception)
    {
        //完全一樣的exception Handling block
    }
}

private void MethodB()
{
    try
    {
        //另一段Business Logic block
        //另一段Business Logic block
        //另一段Business Logic block
    }
    catch (Exception)
    {
        //完全一樣的exception Handling block
    }
}

有沒有發現,每一段Method當中,都有除了Business Logic以外,還有著其他很多其實並非核心的運算邏輯(例如上面的catch區塊...),仔細想想,這樣的情況還非常多,在Method核心的代碼中,總是有一堆跟核心邏輯無關,卻又無法不寫的程式碼,有哪些? 可多了,諸如:權限檢查(permission)、參數檢查(Validation)、例外處理(Exception Handling)、日誌紀錄(Logging)...etc

這些都是撰寫程式碼必須的,但卻跟我們的Business Logic不全然直接相關,這些我們稱為"Infrastructure Logic",在架構上屬於cross-cutting concerns。

這類的程式碼,若能與Business Logic切割開來,能夠立即得到許多好處,諸如:
  1. Infrastructure Logic和Business Logic耦合性降低,兩者分別後更容易重用
  2. 程式碼維護變的更加容易,開發時也可以更專注在Business Logic,不用分心去管雜七雜八的其他程式碼
  3. 程式碼可讀性也變高,閱讀時不會被不相關的code干擾...
  4. ...
總之,似乎好處多多。但由於您可能還沒有辦法理解我們待會要怎麼分割兩者,因此你現在可能完全沒感覺,不急,繼續看下去就會慢慢理解。

=============================================

好,剛才說到,要把程式碼中的"Business Logic"與"Infrastructure Logic"切開來,但是要怎麼切呢? 請回頭看一下上面的那段程式碼:

public void MethodA()
{
    try
    {
        int a = 10, b = 0;
        a = a / b;
    }
    catch (Exception ex)
    {
       //以Config檔案中的 "Policy" ExceptionPolicy設定來處理
       var rethrow = ExceptionPolicy.HandleException(ex, "Policy");
       //如果設定檔說要重丟例外,就重丟
       if (rethrow) throw;
    }
}


基本上,在上面這段程式碼當中,Business Logic只有a=a/b那一塊(雖然只是範例,一點用處都沒有,而且必錯無疑),但為了要預防例外,我們加上了try...catch,而這就是我們所說的 Infrastructure Logic 。

這造成了程式碼之間不必要的耦合性,如果可以切開,那不是挺美好的? 要怎麼切? 有一個美麗的答案,就是... attribute 機制。

想像一下,如果程式碼變成底下這樣呢?
        [ExceptionCallHandler("Policy")]
        public void MethodA()
        {
            int a=10, b = 0;

            a = a / b;
        }
這樣會不會好多了?

我們把原本的try...catch完全拿掉,透過attribute的形式取代,程式碼的效果完全相同,但難看死了的try...catch已經完全消失,開發人員在寫code時,可專注在這段 a=a/b 的Business Logic,是不是清爽很多? 是不是把程式碼中的"Business Logic"與"Infrastructure Logic"切割開來了?

OK,要如何完成這樣的功能? 這就是Policy Injection Application Block的應用"之一"了。

Policy Injection Application Block,讓我們可以在Method上加上attribute(其實還可以透過config檔案來設定,但我們先講attribute,因為我比較喜歡attribute),然後透過attribute來賦予method一個新的功能,來形成Policy Injection。(如果有需要,開發人員也可以自行實作自己的attribute)

==========================================
具體的做法非常簡單,首先,請先在專案中利用NuGet加上幾組Enterprise Library套件:
  1. Policy Injection Application Block
  2. Exception Handling Application Block
  3. Exception Handling Application Block Logging Handler
  4. Logging Application Block
其實本來只需要 1.,但我們要示範加上attribute來處理exception之後,要把exception寫入Log File,所以又加上了2,3,4。

完成後,請撰寫底下程式碼(Console Application):
    class Program
    {
        static void Main(string[] args)
        {
            //抓取Config檔案中的設定,作為configurationSource 
            IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
            //以Config檔案中的設定,建立logWriterFactory 
            LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
            //以Config檔案中的設定,建立LogWriter
            Logger.SetLogWriter(logWriterFactory.Create());
            //以Config檔案中的設定,建立ExceptionManager
            ExceptionPolicy.SetExceptionManager(new ExceptionPolicyFactory(configurationSource).CreateManager(), true);
            PolicyInjection.SetPolicyInjector(new PolicyInjector(configurationSource));
            //故意寫一段會錯的程式碼
            ClassA ClassA = PolicyInjection.Create< ClassA >();
            ClassA.MethodA();
        }
    }

    class ClassA : MarshalByRefObject
    {
        [ExceptionCallHandler("Policy")] //請注意其中的Policy是個參數
        public void MethodA()
        {
            int a=10, b = 0;

            a = a / b;
        }
    }

注意第20行的ClassA,是繼承自MarshalByRefObject。

回到主程式Main當中的前幾行(5-13),我們先前介紹其他Application Block的時候曾經介紹過,基本上就是透過抓取Config檔案中的設定,來建立PolicyInjector, ExceptionManager, LogWriter...等類別。

比較需要注意的是,15行建立類別ClassA實體(instance)的程式碼被改為透過PolicyInjection來建立,至於後續的用法則完全相同。(也就是說,本來你是直接new一個ClassA,現在改成透過PolicyInjection來建立,這有何差別? (先賣個關子,只能說,裡面用到了Unity Application Block,生成出來的ClassA其實也不是以前那個單純的ClassA了...)

 OK,注意第22行,我們在MethodA上頭加上了Attribute,也就是賦予了MethodA()另一個行為,或許可以看成把Policy注入(Injection)到MethodA身上。如此一來,MethodA()就神奇地有了attribute所描述的功能(什麼功能? 當然就是exception Handling)。

如此一來,你不需要在MethodA()當中撰寫try...catch,而這個method發生例外時,自動會把例外導向到Config設定檔中,參數Policy指向的錯誤處理機制。(如果你不太有印象,回頭看看MS Enterprise Library 6.0 (三) - Exception Handling Application Block 那篇)

請留意,上面這段code要能夠順利執行,除了透過NuGet引用Application Blocks之外,還要設定config檔案,至於如何設定,也請參考MS Enterprise Library 6.0 (三) - Exception Handling Application Block 這篇,因為幾乎一模一樣。

===========================================
到這邊,有瞭解了嗎?

基本上,Policy Injection 讓我們以注入的方式,透過設定檔或是attribute,把特定行為注入(加到)某一個method或某一個object身上,這讓我們前面說到的Infrastructure Logic和Business Logic可以切割開來,砍斷其耦合性,便於個別的重用與維護,也讓開發變得更加簡單。(這種把Business與cross-cutting concerns分隔開來的做法,有個經典的名字,稱作AOP - Aspect-Oriented Programming,有興趣的朋友可以上網找找。)

這麼好? 有沒有代價? 有的...不過既然你不知道,就暫時先不提了。

這個好用的機制,是否有可能客製化呢? 例如我自己發明一兩個attribute,掛上這個attribute,某個Method就自動支援身分驗證檢查? 或是支援count? Log? Validation? Cache? ....

其實都有,上面這些很多在Enterprise Library當中早有現成的,不過也有一些從6.0開始被移除,也有一些你必須自己來繼承ICallHandler實作。

但這些...就等到下次有空再說了...

2013年10月13日 星期日

MS Enterprise Library 6.0 (三) - Exception Handling Application Block

有時候心情好,忍不住就多寫幾篇Blog。(當然,心情比較差的時候,可能十天半個月沒辦法安安靜靜的把一些東西整理出來)

前面錄了兩段Enterprise Library的介紹影片,分別談了Unity Application BlockLogging Application Block,這一篇緊接著談Exception Handling Application Block。

由於時空的限制,我現在所在的位置沒法錄製影片,所以只好乖乖用寫的了。

如果可以讓我選擇,我喜歡錄影片遠超過寫文字,原因很簡單,因為我話多,blog有時候忍不住就多寫了幾百字,但這年頭大家都不看字的,害我覺得寫了很無聊。寫了沒人看不打緊,花的時間很多,年紀大了越來越懶,用講的比較快,還可以當作上課的彩排甚至教材,所以我喜歡錄影遠超過寫文章。

岔題了。

Exception Handling Application Block,顧名思義就是系統中處裡例外的模塊,大家都知道,我們會在程式碼中加上try...catch來處理例外,程式碼常常會像是這樣:
            try
             {
                 int a = 10, b = 0;

                 a = a / b;
                 Console.WriteLine("done!");
                 Console.ReadKey();
             }
             catch (Exception ex)
             {
               //如果發生例外...就...
             }
這樣的程式碼沒啥太大的問題(除了因為是範例所以一定會發生例外之外...)。

但如果像上面這樣的程式碼一多,我們就會發現,每一個try...catch裡面都是另一段不受管理的複雜的錯誤處裡邏輯,可能是寫log、可能是發mail、可能是retry...,不僅如此,一旦例外處理區塊寫死之後,例外處理區塊常常本身就是一個大累贅。

還有,發生例外的可能性和類型很多元,上面這段程式碼非常簡單,只可能得到一個 "除以零" 錯誤。但真實世界中,如果是一段比較複雜的程式碼,有網路連線、有檔案處理、有數字計算、日期計算...而我們要針對可能發生的不同的例外分開來處理(例如發生檔案相關錯誤就發mail、發生網路錯誤就寫file log,發生其他運算錯誤就寫event log...,那你的catch中的程式碼就精彩了!!!
             try
             {
                 //如果這邊很長,或是進行了各種不同的動作             }
             catch (Exception ex)
             {
                 //如果是DivideByZeroException
                 if (ex.GetType().Equals(typeof(System.DivideByZeroException)))
                 {
                     //...
                 }
                 //如果是WebException
                 if (ex.GetType().Equals(typeof(System.Net.WebException)))
                 {
                     //...
                 }
                 //如果是FileLoadException
                 if (ex.GetType().Equals(typeof(System.IO.FileLoadException)))
                 {
                     //...
                 }
             }
所以可以想見,當我們在真實世界的專案當中,catch部分可能要針對各種不同型態的例外,進行各種不同的處理,再加上又要考慮是否rethrow,複雜度又更高了...

也因此,我們需要一個一致性的例外管理模塊,這時候, Exception Handling Application Block 就可以派上用場了。Exception Handling Application Block 可以做到:


  1. 用統一的程式碼來管理例外
  2. 透過設定App.Config來處理例外,如此一來若要改變例外處理的方式,就可以不用改程式碼
  3. 可針對不同類型的例外設定不同的處裡方式
  4. 可隨時增加或減少某種例外的處理方式(例如發生例外時的紀錄本來只有發email,但要改成同時寫入db,可以透過設定的方式來進行)
知道了用途之後,我們就來看看實際上怎麼用。

Step1:現在專案中加入:
  1. Exception Handling Application Block
  2. Exception Handling Application Block Logging Handler
  3. Logging Application Block

本來我們只需要加入第1個,但因為我們處理Exception的方法是寫Log,因此也加入了2,3



Step2:請參考底下的程式碼:
底下這段程式碼是Console Application,基本上3-10行是Enterprise Library的相關程式碼,主要是從設定檔來建立所需要的各種物件。(待會會教大家如何建立設定檔)
16行是會觸發一個除以零錯誤的代碼
而23,24則是我們的核心了,我們透過ExceptionPolicy這個 enterprise library的錯誤處理類別,來處理錯誤,採用的是名稱為Policy的設定檔內容。

-------------------------------------------------
static void Main(string[] args)
{
    //抓取Config檔案中的設定,作為configurationSource 
    IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
    //以Config檔案中的設定,建立logWriterFactory 
    LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
    //以Config檔案中的設定,建立LogWriter
    Logger.SetLogWriter(logWriterFactory.Create());
    //以Config檔案中的設定,建立ExceptionManager
    ExceptionPolicy.SetExceptionManager(new ExceptionPolicyFactory(configurationSource).CreateManager(), true);
    //故意寫一段會錯的程式碼
    try
    {
        int a = 10, b = 0;

        a = a / b;
        Console.WriteLine("done!");
        Console.ReadKey();
    }
    catch (Exception ex)
    {
        //以Config檔案中的 "Policy" ExceptionPolicy設定來處理
        var rethrow = ExceptionPolicy.HandleException(ex, "Policy");
        //如果設定檔說要重丟例外,就重丟
        if (rethrow) throw;
    }
}
--------------------------------------------------------

OK,所以瞭解了程式碼之後,就知道關鍵在名稱為Policy的設定檔內容,這個設定檔的內容決定了我們要如何處理、以及要處理哪些類型的例外,並且決定了處裡完例外之後,是否要重新丟出例外。

知道了之後,我們就來看如何建立這個設定檔,請參考底下的影片,我們的動作是:

  1. 從VS2012開啟設定檔編輯器
  2. 建立Exception Handling Settings( 注意名稱為 Policy,且post HandlingAction設為None )
  3. 建立Logging Exception Handler(配合Exception Handling Settings)
  4. 在Logging Exception Handler中,指定Logging Settings( 注意名稱為 General )
  5. 建立Rolling Flat File Trace Listener


最後,我們來看執行結(請留意,當修改了設定檔之後重新執行,你會發現程式對錯誤的處裡方式也隨著設定檔而蓋變了):

btw,   請原諒我只能很扼要的介紹Enterprise Library中的exception handling application block,其他更多精彩的功能,請自行參考微軟Enterprise Library網站囉。

MS Enterprise Library 6.0 (二) - Logging Application Block

Logging Application Block,其實是相當簡單的機制,基本上就是把紀錄Log這件事情,設計成一個獨立的模塊,讓開發人員可以方便重用。
 
Enterprise Library當中,方便好用的地方在於,已經內建了多種Listener供開發人員使用,讓你將Log寫入各種不同的位置,諸如Event Log, File, DB, eMail...etc,如果有需要,您也可以自行繼承建立新的Listener,衍生出新的紀錄輸出位置。
 
要如何利用Enterprise Library中的Logging Application Block,輕易的在程式碼中透過單一的方式寫入Log,並且支援可隨時透過設定(不需要調整或修改程式碼)即可動態調整Log寫入位置,或增減各種不同的Log存放位置呢?

底下這段影片可提供您參考。 如果你的網速可以,建議以720p解析度觀賞:
( BTW, 如果你覺得我前面簡介Enterprise Library講得太囉嗦了,可以從 3:38 開始看Logging Application Block)
 
 

2013年10月12日 星期六

MS Enterprise Library 6.0(一) - Unity Application Block

開發人員在自己很辛苦的寫Code的同時,如果有時間,不妨多參考一些經典的套件或組件,從其中不僅可以學習到如何更快速有效的開發出中大型系統,同時間也可以參考前人的智慧,吸取他人的經驗,用來開發自己(公司)的套件或函式庫。

每每上課時,聽到開發人員撰寫代碼的重用率,幾乎都低到不行,即便專案的形似類似,卻常常重寫系統,不免有些感慨。如何能夠讓開發人員以更少的時間,完成更有價值的工作成果,實在是開發人員應該要關注的技巧。

底下這段影片,是答應學員要錄製的,內容來自我在今年(2013)Microsoft Techdays Taiwan研討會上介紹Enterprise Library的一個小片段,以一個具體的HR系統,薪資計算作為實例,來討論Unity Application Block的具體應用,當然,這個的背後就是IoC(Inversion of Control)與DI(Dependency Injection)的實現。

研討會中,總是用飆車的速度把原本要講超過半小時的東西,在5-10分鐘講完,對學員來說難免有些囫圇吞棗,導致吸收不良,有機會我盡可能把研討會中的內容,再整理成影片分享。

這段影片錄的不是很理想,甚至有些解釋不是很到位,但請原諒我時間真的不夠,沒能抽出時間再剪接修改(我的影片從來都是一次錄完,中間失敗了就整個重錄),只好先以這個版本拋磚引玉一下,希望大家別介意。跟以前一樣,如果你覺得影片的內容對你有些幫助,就多一點分享給其他人,如果有需要改進的地方,請直接mail給我囉。

 如果你的網速可以,建議以720p解析度觀賞:
( BTW, 如果你覺得我前面講得太囉嗦了,可以從 5:24 開始看實例 )

2013年9月26日 星期四

techdays 2013 - 圓滿達成

很高興今年Techdays我的兩個場次在幾乎沒有任何意外的狀況下,總算順利完成了。

今年的主題有兩個部分,分別是:

開發主管的架構設計第一課 - 善用 Enterprise Library 6.0 及 Patterns & Practices這一堂課我自己很喜歡,準備了非常多的內容,導致大超時(意料之內),因為實在覺得砍掉太多的投影片很捨不得,其實比起我先前準備的內容,大概還是砍掉了近五十張slides,我會找時間把完整的版本,以及錄好的展示影片陸續的提供給大家。

Windows Phone 8 開發深入解析及實用技巧介紹這一堂課則是WP8新功能的介紹,從重要的動態磚、螢幕鎖定、中文語音辨識、App to App Communication、到近場通訊(NFC) 。我盡可能在有限的時間內把WP8重要的功能展示給大家,並且介紹程式設計的方式。

這兩場的投影片、操作影片、範例,我會陸續提供給大家。

update 2013/9/28 : 今年的slide會統一由techdays主辦單位提供,請開發夥伴們再稍等一下囉。

update 2013/10/03: Techdays Taiwan 2013 material 相關下載位置 http://technet.microsoft.com/zh-tw/hh524389(v=msdn.10).aspx

2013年9月15日 星期日

假日撰寫吾code,不亦說乎 ; 寫code不問時程,不亦樂乎 ; code而不求天下知, 不亦君子乎~

寫Code真的是一種樂趣。

還記得當年年輕時候的熱情?

如果不問目的,不趕時程,假日在海邊或咖啡廳,面對著往來的人群,亦或是看著山嵐聽著鳥語聞花香,然後寫只是為了好玩~全然無用(沒有商業目的)~不趕時程~沒有壓力地寫著Code,真的是一種外人無法理解的享受。

我常常在想,一個Truly Developer,會不會到死前最後一刻,即便無法下床,行將朽木,但腦袋裡還有那麼瞬間想著的是,某一段自己不為人知的代碼,或是超越時代的架構設計?

我記得十多歲的時候,寫程式真的沒有任何目的,只是想實現一種可能性。當時,腦袋中有數不完的創意和想法(從現在的我來看,當年的想法絕大多數都沒太大意義也不值錢),等著我嘗試和實現,每天都忙著在電腦前驗證腦袋裡的想法是否可以通過編譯,幻化出螢幕上絢麗的各種彩蝶...

或許隨著年紀、工作、職位的改變,導致程式設計和架構規劃,慢慢變成必須要每天與時間賽跑、與完全沒有系統美感的客戶折衷妥協、與專顧利潤不管品質的老闆拉扯...但偶爾,我是說偶爾,你該為自己規劃一個專案,沒有時程壓力、沒有獲利考量、沒有資源或技術限制,安排幾個假日去實現自己的夢想...或許,你會慢慢回憶起當年的熱情... 找到可以持續的動力...

2013年8月28日 星期三

元件存放區已損毀 Error Code: 0×80073712

資訊科學以及開發人員的養成訓練和經驗告訴我們,發生問題一定是有背後的原因的。網路上常常有人歸納於人品、或七月沒拜拜、或放在Server上的零食過了保存期限(或是加了塑化劑),我要說,這都是不科學且沒有根據的。

話說自從我買了新的NB之後,一直沒有認真寫程式,可能是因為上帝覺得我這樣混也不是辦法,所以強迫我非得寫個App不可,我在蘑菇了幾天之後,終於重新把開發環境和WP8 SDK裝起來,過程出奇的一切順利(誰說人品有問題來著???)...

WP8模擬器需要Hyper-V,這不是問題,我可是i7的ultrabook呢...

正當我這樣想的時候,shit,Hyper-V開不起來,以前沒看過的錯誤訊息...

元件存放區已損毀


 
 
什麼鬼啊,本著實事求是的精神,我決定要認真找原因,我不相信跟今天大樓普渡我理都不理有什麼關係。

經過30分鐘後,找出解法了,首先,用管理者身分開啟Command Line,接著輸入:
DISM.exe /Online /Cleanup-image /Scanhealth
DISM.exe /Online /Cleanup-image /Restorehealth

執行結果如下:



搞定。

後記:這個問題其實估計跟預裝的Windows 8我把它升級成Windows 8 Pro有關。如果重新安裝Windows 8 Pro,應該不會有這個問題,本著實事求是的精神,這個測試,我留給其他人做了。

後後記:話說我Search的時候看到這篇,這苦主發生的問題跟我一模一樣,連機器都是同一款,我在想,說真的,最近這十年因為internet的出現,世界變小了,學習變快了。如果是二十年前,在地球兩端的兩個人,可能得各自為了碰到的問題傷腦筋,但現在,我只是Search,就可以找到別人留下的足跡...一方面感謝,一方面感慨...

2013年8月24日 星期六

你為了什麼寫Code呢???


在網路上看到一個小朋友提到最近看到一篇文章,講到的程式設計師的薪資。這位寫PHP的同學,發現自己可能領到的薪資相較於用其他技術的開發人員低,比較起來是倒數的,有些忿忿不平。

原始文章在這裡:
http://www.inside.com.tw/2013/08/23/average-income-per-programming-language

姑且不管上面這篇寫的到底對不對、這樣的統計數據有沒有道理,其實...我想說的完全是另一件事情。我想談談為何軟體業不賺錢,以及程式設計師的薪資問題。或者這麼說吧,你真心想在這個行業繼續奮鬥,卻又真的覺得自己薪水不夠想要高一些...OK,那你可以繼續看下去。

在台灣,在今天這個時代,若你只『專注於』寫程式,是不太可能賺到大錢的。可以溫飽、可以糊口、也可以集畢身積蓄買台重機...這都OK,但若你想買台北市的房子、或買買BMW、Benz玩玩,那可能就輪不到你了。年輕的時候,你也許會覺得無所謂,但到了一定的年紀之後(30,35歲),你會慢慢發現這似乎怎麼有點不太對...

也就是說,我們在研討會上跟大家說,寫程式要有愛,學技術要有愛,不然撐不久,這不是說著玩的,是認真的...老師在台上講、沒睡著的,就應當聽。

這一路以來,我們沒有轉行,不是因為覺得這行業可以幫我們賺到大錢、或是因為手上掌握了哪種關鍵的應用技術、還是在台上很風光、可以享受學員崇拜的眼神,或是在案子裡面可以呼風喚雨...從來都不是(因為都沒有)。

這一路以來,我們沒有轉行,是因為我們習慣了看世界的時候,用的是與世人不同的另一種角度;我們習慣了看到問題,就思考著如何可以第一時間找出答案;我們習慣了出現新的技術時,以朝聖的心情蒐集、整理、比較、分析、再消化吸收;我們習慣了會心這小小的社群裡面的人,才能理解的幽默。當然,碰到一些IT或3C阿宅希望我們幫忙解決一些電腦問題時,偶而也享受著這些不明就裡的外人,剎那間完全搞錯對象也搞錯方向的崇拜。(有統計指出,幾乎每一個Developer,都幫女生修過電腦...)

但為了賺大錢? 很抱歉,一直都不是,也從來沒機會。

我也曾經也有著不明白的時候,要知道,一個商業Developer的養成其實相當不容易。除了,必需學習的技術少說也數十種,大多數Developers在養成過程中,看過的專業書籍數以百計,而技術的變化或更新的速度我敢說是全球各種行業之冠,能夠在這樣的壓力下活下來的,就算不是把自己搞得拋家棄子,大概也是在年輕的時候肯定有過一段不為人知的苦讀歲月。這世界偶而會把不學無術的宅男跟Developer聯想在一起,但其實,這等級根本不可同日而語。

要知道,Developers,外表服裝看起來就算有點宅,但其實也深具內涵。不夠聰明的,絕對不可能成為優秀的Developer。沒有經歷過跟鍵盤螢幕奮戰的歲月,沒有閱讀過上百本專業書籍,是不可能成就一個專業Developer的。

既然要成為Developer那麼難,照這麼說,這個行業中的佼佼者一定都很賺囉???
NOT AT ALL! 應該說...一丁點都沒有!

前面說過,我以前也很不明白為什麼,但隨著年紀稍長,慢慢可以理出一些頭緒。

首先,你必須承認,大多數的Developer都不太喜歡賺錢,所以沒錢是挺有道理的。我小時候的管理學老師跟我說,你要先愛錢,才能賺到錢,我年輕的時候覺得這聽起來好市儈,但現在我明白了。

因為Developer愛技術,不愛錢。

這麼說吧,如果你跟Developer說,深夜一點半有一個30分鐘的線上英文轉播,由財經大師告訴你全球股市未來的趨勢,並且傳授你準確的投資標的與方向,我跟你打賭大部分的Developer的腦袋裡根本會忘記這件事情,更不用說晚上還爬起來看了。

但是,如果這是一場北美最新的技術研討會呢? 或是最新款手機新功能的發表會呢? 就完全不一樣了,不需要提醒,不用吆喝邀約,我不只一次在FB、Lync、Skype上和社群的朋友們一起準時地從家裡連線,收看即時現場的技術發表會轉播,即便在晚上一兩點,Developer還是能從床上爬起來看...這是熱情,是愛! 不是嗎? 除了 王建民 或 林書豪,還有誰能讓developer這樣呢?

以前我老闆說過一句名言,『別跟我說你很忙,你永遠有足夠的時間花在你熱愛的事物上』。所以我說,Developers愛技術,不愛錢。

而我那睿智的老闆,隨後又說了一句更重要的話:『你的時間在哪裡,你的成就就在哪裡。』Developer不花時間想想怎麼賺錢,怎麼會有錢呢?

但如果因為這樣,Developers注定就窮,倒也不是。因為你總是會找到那些年紀輕輕就賺了一大筆錢退休的年輕小夥子的創業例子,或是在某一家公司領了不少股票的資訊高手,不過你有沒有發現,這些故事,大多都不會發生在我們寶島台灣?

所以議題就轉變成了,為什麽台灣的Developer賺不到錢? 小時候我也不太懂,但隨著角色的轉變,我慢慢接受了,原因其實也很簡單。

你要知道,經濟學告訴我們,所有的獲利都建築在需求上。而需求的強弱,決定了 客戶付錢的可能性、付錢的乾脆程度、以及金額的多寡。客戶付錢的多寡則決定了你所在(或你所擁有)的公司的獲利,而你公司的獲利決定了你的(員工的)薪資。

我搞了大半輩子技術,才慢慢明白(接受),不是因為你很強,就表示你會有很高的薪水,這根本是兩碼子事。薪資其實跟你所在的公司、你所在的地點、你所在的國家,有著密不可分的關係。

記得,所謂的薪資,是你公司所能(所願意)把你留下來的最低成本。這個金額的高低,取決於:
1.你所在的公司賺不賺錢
2.你的市場競爭力好不好(你敢不敢離職)

你的公司越賺錢,你的公司就會越願意(越能夠負擔、也越有可能)花更多的錢把你留下,這樣,你的薪資相對而言就會比較高一些,如果你的公司不賺錢,即便你很優秀,你要加薪的機會也就低了。

而從你的角度來說,是相對的狀況,你越有市場價值、競爭力越高、跳槽到隔壁公司可以多談個一兩萬,你的薪資當然就高了,如果你不敢離職,不願意出去闖,不敢拚拚看,當然就維持原本的薪資好幾年不動。要知道現在不是很景氣,軟體業又是個弱需求,公司沒事幹嘛幫你加薪呢? (記得,所謂的薪資,是你公司所能把你留下來的最低成本。)

說到弱需求,可能很多技術人員不願意承認,但事實就是,很多軟體並非企業迫切需要的。甚至很多軟體根本是我們催眠企業,硬告訴他你有這個需要的。對於企業(或人)來說,沒有這個就不行的,這是強需求,沒有這個也不會怎樣的,就是弱需求。OK,那,這麼說吧,你寫過幾套軟體,是企業沒有用它就會倒閉的呢? 我看大多數人沒有。

所有的軟體廣告,大多都只會說,用了某軟體會提高企業競爭力(但誰算過有多少?) 或是用了可以降低成本(真的???) 或是用了這套軟體可以節省人力(但省下來的人要幹嘛呢? fire掉?) 總之,導入軟體所需要的成本先不說,導入後能不能有成效,其實還是個未知數,也因此,軟體在不景氣的時代,很明確的是個弱需求,弱爆了,比加了色素香料的麵包還要弱。(你可能會看到商業期刊上某些歌頌著某種軟體幫企業如何如何賺錢的...那肯定是行銷廣告無誤)

不能說全部,但大部分的軟體,都是弱需求。再加上,台灣是中小企業較多的狀況,所以軟體的需求相形之下就更弱,因為使用軟體的企業本身規模越小,就越難看到軟體的價值。導致開發軟體的專案公司在台灣削價競爭以求苟活,幾乎是沒有辦法的事情。這樣我們就不難理解,為何台灣的軟體業不容易賺錢。(所以也不難理解,為何Developers你的薪水並不高)。

請記得,如果你的公司不賺錢,你就不會賺錢。如果你公司的客戶不賺錢,你公司就不會賺錢。這樣,你明白了嗎? 你能力強不強,跟你會不會賺錢,有關,但不是只有這件事情有關。即便你是一個優秀的Developer,決定你賺不賺錢的因素還有很多,你選擇了哪一家公司,是一個最基本的重點。

想通了嗎? 你用什麽技術決定(暗示)了你們公司的客戶是誰 → 你們公司的客戶是誰決定了你們公司賺不賺錢 → 你們公司賺不賺錢決定了你的薪水高低 ... 這中間,其實大致上與你個人的強弱無關。

你說,可是我能選擇的公司不多耶,都是公司選我...那請你看完這篇文章,立刻跟我(或其他教育訓練中心)聯絡,我覺得你應該迫切需要進修。

如果你是Developer,又想賺錢,就把你的能力(特別是英文能力)培養好,然後(請注意這是重點),去找一家能夠付得起你高薪又會賺錢的公司,先擠進去,接著去證明你自己值得待在那裏。但...如果台灣沒有適合自己的呢?

前面說過,你的薪資跟你所在的公司、地區、國家...都有關。坦白說,我一直在台灣寫Code真的是因為這是我的興趣,而且我對這塊地有依戀。然而如果developer一心想賺大錢,學好語文,試著離開台灣出去走走,到新加坡、香港、美國、或中國,都可能會有更多的可能性或機會。也因此,到頭來,這其實是ㄧ種取捨...

在寫這篇文的同時,網路上傳來了Ballmer準備退休的消息,微軟因為他的準備退休,股票大漲了超過6%,有趣的是,新聞網站推估Ballmer自己可以因為這樣大賺,以鮑默持有3.3億股微軟股票計算,他瞬間增加8億美元(240億台幣)財富。

Develoeprs!Develoeprs!Develoeprs! 其實用喊的比你用當的來得賺!

王文華講過一句話:幸福像是自由,有些人是與生俱來的,有些人則要拚了命流血爭取.....我想,財富也是...

Developers與其想著錢途,不如去愛上你的Code。
但如果...不愛了呢? (下回再說)

2013年7月14日 星期日

你的財寶在哪裡,你的心也在那裡...

部落格中好久沒有寫寫心情了...

主日,早上主領敬拜的弟兄提到,最近搬家,過去視為珍藏的許多論文、書籍、和知識,在搬家過程中全都捨棄了,過去前幾年覺得重要的,如今看起來卻似乎都沒那麼有價值...

碰巧前一陣子我也剛搬完家,30歲的時候搬家,跟40歲的時候搬家,最大的不同是,很多東西我開始覺得我搬不動,也不想搬了:或許不是實際的重量多重,而是我覺得這些東西放在我生活裡、或是我生命裡,它無形的重量太重,佔有的空間又太大,讓我很容易忘了其他更重要的事情...

所以這次搬家,我丟掉的比上次搬家時所丟的又多更多了...連我自己寫的書,都只留下了一本,更不用說其他的了...搬完之後,老婆跟我說:我們家徒四壁耶..我說:是啊,你不是一直想要有更大的空間嗎? 現在有沒有很清爽??? :)

那時候,我心裡在想,我們手上掌握的技術、整理的知識、考完的認證、拿到的獎盃和獎狀...種種引以為豪的成績,真的那麼重要嗎? 我現在拼命努力的,會不會幾年以後,搬家時,又毫不猶豫地被我捨棄了呢?

我想到聖經上的一段話:「不要為自己積攢財寶在地上;地上有蟲子咬,能銹壞,也有賊挖窟窿來偷。只要積攢財寶在天上;天上沒有蟲子咬,不能銹壞,也沒有賊挖窟窿來偷。因為你的財寶在哪裡,你的心也在那裡。」

或許你不是基督徒,但上面這段話,我最喜歡的是:『你的財寶在哪裡,你的心也在那裡』...對你來說,你的財寶是什麼呢???  我有一個好朋友,結婚之後,工作還是佔據他人生當中不少的時間,他和他的另一半,都是非常忙碌的中階主管,但自從生了孩子之後,我明顯的地看到了他們的改變...

年輕時,我們常常談著將來要怎樣創業,或是合夥開家公司,或是用技術改變這個世界:自從小孩出生之後,他最在意的是孩子的健康、關注的是怎麼教育對孩子最好、掛念的是小孩將來的成長規劃...創業的事情我當然也不再提了,他只希望在這一波景氣低谷中,能夠確保工作的穩定。

我沒有小孩,但我想我能理解這樣的心情。

前陣子和剛結婚的年輕工程師聊天,他剛進到一個嚮往已久的工作環境,身邊的同事就是以前崇拜的技術明星,過去在大型研討會的舞台上才能夠瞻仰的風采,現在每天出現在自己的身邊,興奮的程度恐怕跟中了尾牙頭獎差不多...

我聽了快一個月他述說自己公司顧問講師們的輝煌事蹟、風光的專案經歷、帶有能力與強大說服力的講演風采...等,但半年後再次見面,他卻告訴我有些猶豫想要換個工作...我訝異的問他,那不是他夢寐以求的環境嗎? 他告訴我,他開始明白,原來所有光鮮亮麗的呈現,背後所要付出的時間,可能不是每一個人都能承受的。他其實進去之前已經有心理準備,卻沒想到衝擊依舊如此之巨。

『我並不排斥加班或是壓力大的工作,但如果要我放棄自己的生活,或犧牲我的家人,用我的整個人生來換台上那風光的幾小時,我想我可能不是真的很適合』他說『我開始理解你以前曾說的,在工作上要很強其實不難,但要讓工作和生活取得平衡,那才真的是不容易。』

我以前說過這樣的話嗎? 我忘了。
但是,在工作和生活中取得平衡...這其實是我學了好久依舊學不太會的功課...

文末,我想起了五年前的一個廣告...



沒有真心期待你成功的朋友、失去你摯愛的親人,就算獲得工作中再大的成就,也只有你自己一個人能陪著自己享受,相信我,那將會是很無趣的。

2013年6月14日 星期五

在Web Form專案中使用Rzaor上Azure WebSites的問題

先不談問何需要在WebForm當中使用Razor WebPages,這一篇主要還是討論到的問題和解決的方法。 首先要在WebForm中使用Razor不是太大的問題,建立一個HTML Page把副檔名直接改cshtml即可:

接著我們就可以撰寫Razor語法了(我找一天完整一點介紹Razor以及他的意義,但還沒寫之前,gelis的這一篇不錯,如果你喜歡讀英文,可以看這篇)。

OK,撰寫一段簡單的程式碼如下,結果一執行,馬上發生錯誤:

我們很乖的依照指示,到web.config中改成:
<configuration>
 <appSettings>
   <add key="webPages:Version" value="2.0"/>
 </appSettings>
<system.web>
  <compilation debug="true" targetFramework="4.0" />
</system.web>
</configuration>

OK,可以work囉。


但悲劇發生在上Azure WebSites時:

本來以為是Azure websites看不懂cshtml,還我改了一陣子MIME設定,後來想想不對,如果看不懂就應該不能run MVC 的razor才對,所以又轉往另一個方向嘗試,折騰了半天,原來Azure websites尚未支援2.0。 立馬到Azure WebSites設定畫面調整看看:

設定完成之後,搞定囉。 cshtml的razor頁面可以混在WebForm中上Azure囉...

先寫到這邊(其實還有一個在cshtml page中存取資料的問題...改天繼續)

==================================
沒事幹嘛在ASP.NET WebForm中混入Razor呢?

其實我也有點掙扎。 這一陣子有個案子是以MVC來設計,開發的同仁跟我說,選用MVC其中一個原因是他討厭WebForm中的WebControl,總是沒有辦法隨心所欲的調整UI,不管套入CSS或是選用哪一套JavaScript Framework,實在都不容易整合。

某種程度上我是接受的,因為WebControls自己reder出來的HTML,想要調整很難不寫後端C#(VB) code,來微調WebControl的HTML輸出。但如此一來,前端又有寫死在.aspx中的JavaScript,後端又有透過C#(VB)動態產生的JavaScript,整個頁面的呈現就算能夠達成我們要的效果,但已經讓後續維護越來越困難。

這是很多人選用MVC的動機之一...但,如果這只是唯一原因...對專案來說背後的代價也不算低。

因為寫慣了WebForm(或Windows Form)的開發人員轉往MVC會有一段掙扎的時間(我發現反而原本從沒寫過WebForm或WindowsForm的開發人員卻比較容易進入),而且MVC要寫的漂亮,且維持MVC的精神,其實對於物件(OO)操作的觀念需要比WebForm對於OO的觀念來的更精實才行。而在採用MVC來開發之後,處理UI時想要用比較短(比WebForm或Silverlight還快)的時間來達成相同的效果,大概非得用上一兩套JS Framework不可,這些都增加了入門的門檻和學習(開發)的成本。 而URL Routing和Controller的觀念也是必須的,導致我在專案中想讓ASP.NET WebForm開發人員立刻接手MVC開發工作,常常會發生一些衍生的成本。

為了兼顧網頁UI呈現的自由度,又不想用MVC這麼大一套架構,因此我們最近開始採用Razor Page在WebForm專案中,搭配自己的code generator(關鍵其實在這裡 :) ),並依照專案的不同選用JS Framework。這會迫使開發人員必須放棄WebControls來設計UI,而直接用HTML/JS來處理,搭配Razor Page以提高開發的效率。

(那為何不用inline ASPX? 可參考上面gelis那一篇中的解釋)

這是一個嘗試(也就是說我也不確定這樣一定是好的,如果有想法非常歡迎一起討論)。在.NET Web開發的領域中,已經累積了相當多不同的技術,傳統的WebForm有WebForm的好處,MVC有MVC的優點,Silverlight有Silverlight的價值,Razor有Razor的便利...也因此,在熟悉每一種技術之後,看看怎麼讓開發成本最低,後續的維護便利、程式碼的重用性最高...是我們在開發專案的目標。

2013年6月9日 星期日

ASP.NET Reporting - 如何讓SSRS中TextBox的Go To URL Action中跳新視窗

SSRS對於ASP.NET開發人員來說實在是一個很好的工具,畢竟,對很多MIS/IT所服事的大老闆來說,資訊系統
唯一的價值,其實就是那一份份的報表。

如果你有用SSRS,一定會發現文字方塊是可以設定成超連結的,關鍵在於TextBox的Action屬性,只需要設定成Go To URL,然後在Select URL那邊放入網址即可: 但你找了半天,居然沒有可以設定點選該URL的Target設定位置,那...如果要開新視窗怎麼辦呢??? 好問題!!! 其實,這個Go To URL有一個更有趣的設定,可以解決這些問題,你可以直接在Select URL中,輸入底下內容:
沒想到,居然可以輸入JavaScript,如此一來,在報表中點選該連結,就可以開新視窗囉。

=============================================================
既然可以開新視窗,那可不可以更進一步的???

答案也是可以的,SSRS真是個好物。

2013年6月6日 星期四

ASP.NET WebForm Forms驗證整合Google oAuth驗證

ASP.NET從4.x開始,支援不少重要的機制,也不知道是因為用的人變少了,還是因為大家都沒空,所以ASP.NET WebForms相關的中文post比起其他技術相形之下少的可憐。

最近開發團隊中有夥伴需要透過ASP.NET WebForm來整合Google/Faccbook/MS的身分驗證,當然,我們都知道現在大家都支援oAuthOpenID了,最理想的狀況是讓我們家的網站跟MS自己的網站一樣,User只需要登入一次,就可以跨網站跑來跑去不需要重新登入,同時,我們的網站也不需要負責維護用戶的帳號密碼,而是透過Google/Faccbook/MS幫我們做身分驗證。
(有空我會畫張圖,上面這張是出自oauth.net)

簡單的說,就是我們的網站的用戶只需要有Google/Faccbook/Microsoft Account等帳號,即可登入我們的網站,而我們的網站也不需要傷腦筋身分驗證的事情,畢竟,驗證是一個可能導致風險的機制,也是駭客進入你的網站的第一道防線,如果隨意設計可能後患無窮,與其自己辛苦,不如透過oAuth機制幫你驗證用戶身分。

前面說過,在ASP.NET要實現這樣的功能,從4.0之後的版本,大幅簡化了工作流程,甚至,你現在只需要透過DotNetOpenAuth.AspNet套件即可完成。 我們以底下這個ASP.NET WebForm 4.0與Google帳號整合的驗證機制來示範,我們建立一個新的WebForm網站:

我刻意用ASP.NET Empty Web Application,因為這個範本比較乾淨,甚至連app_start都沒有,這樣比較容易說明。 接著,請進入到我們的ASP.NET專案,在VS2012中開啟Package Manager Console(主選單--> Tools --> Library Package Manager --> Package Manager Console),並依序輸入:

Install-Package Microsoft.AspNet.Membership.OpenAuth
  和
Install-Package DotNetOpenAuth.AspNet

輸入後,VS2012會執行一些動作...


你會發現Visual Studio在你的專案中加入了一堆有的沒的.dll,完成後大致如下:

主要是頭底上那幾個Microsoft.AspNet.Membership.OpenAuth... 接著,請在專案中加入Global.asax:

並且在Application_Start中加上這一行:(以整合Google驗證為例)
protected void Application_Start(object sender, EventArgs e)
 {
      OpenAuth.AuthenticationClients.AddGoogle();
 }

然後我們要建立幾個頁面,分別是default.aspx, login.aspx, GoogleCallBack.aspx
  1. default.aspx 是我們的首頁,在首頁中會顯示登入用戶的資訊,如果發現使用者沒登入,則導入到login.aspx。
  2. login.aspx登入頁面,過去我們是在這個頁面中放入login控制項,而現在我們則在這個頁面中,把用戶帶到google去做登入驗證
  3. GoogleCallBack.aspx則是google幫我們驗證完之後,要將用戶帶去的那個頁面
在default.aspx中,我們的程式碼是:
protected void Page_Load(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(User.Identity.Name))
        this.Label1.Text = User.Identity.Name;
    else
        Response.Redirect("login.aspx");
}

在Login.aspx中,我們的程式碼是:
protected void Page_Load(object sender, EventArgs e)
{
    OpenAuth.RequestAuthentication("google", "~/GoogleCallBack.aspx");
}

最後,是重要的GoogleCallBack.aspx
protected void Page_Load(object sender, EventArgs e)
{
    var returnUrl = Request.QueryString["sid"];
    var authResult = OpenAuth.VerifyAuthentication(returnUrl);
    if (authResult.IsSuccessful)
    {
        System.Web.Security.FormsAuthentication.SetAuthCookie(authResult.UserName, false);
        Response.Redirect("default.aspx");
    }
}

別忘了Web.Config中必須要設為Forms驗證:
<system.web>
<authentication mode="Forms"></authentication>
   ...
   ...

接著,就可以試試看囉....你會發現當進入default.aspx頁面,如果用戶尚未登入,系統會導入google驗證畫面:

當用戶登入後,則會出現此要求授權畫面:

這個畫面只會出現一次,當用戶接受之後,未來登入時就不會出現,接著,系統自動將程式導入到我們先前設計的GoogleCallBack.aspx,在該頁面當中,我們透過API取得用戶帳號,並且透過SetAuthCookie保留用戶身分,再導回首頁,如此就完成google與ASP.NET WebForm Forms 驗證的整合囉。



Source Code:
https://github.com/isdaviddong/aspnet4WebFormsAuthAndGoogleoAuth

2013年5月29日 星期三

升級舊版 Visual Studi 2010 的 SQL Express .mdf 檔案到 Visual Studio 2012

上課的時候,我們常會讓學員用SQL Express來開發或測試ASP.NET應用程式,但是換了新的開發環境之後,你可能會發現,Visual Studio 2012開啟舊版的.mdf檔案會發生底下錯誤:
 
這時候,若你要升級舊版.mdf,可以在Server Explorer中,點選該mdf:
 
 
按滑鼠右鍵選擇【Modify Connection...】,接著選【Advanced】:
 
接著再出現的Advanced Properties視窗中按下OK,然後Advanced Properties視窗關閉後,再按下OK,接著會出現底下畫面:
 
 
一旦按下Yes,該.mdf資料庫就會轉換成新版的囉,接著我們就可以在VS2012中正常存取了。(注意:但Visual Studio 2010就不能讀取囉)
 
如果你不想轉換而是想共用,也可以參考底下說明:
 



2013年5月25日 星期六

反對政府以任何理由封鎖任何網站!!!

最近一直看到這個訊息,智慧局好熱心主動的想打擊盜版,然後好的不學學些惡霸國家封鎖自己人民的網路,看著看著,我心裡就更納悶,這到底是怎麼回事??? 這是什麼邏輯?

為了保持理性,我努力的從智慧局的角度想這件事情,但依舊想不通,想要防止盜版,所以就封鎖(擋掉)國外的網站,讓台灣島上的人看不到某些架設在國外的網站的內容,可是,這樣能保護什麼呢? 充其量不過就是保護台灣廠商(或外國廠商)在台灣這塊小島上的獲利,讓這些廠商能夠賺得到台灣人的錢,但這樣的保護真的有價值嗎?

誰都知道台灣是個小島,上面沒多少人,不管是賣電影賣唱片賣什麼玩意兒,台灣都只是全球市場(或全球華文市場)中的一小塊,政府你放著全世界那麼大一塊95%的市場在盜版不努力去想辦法(不管是無力防堵或不想防堵),反倒把腦筋動到台灣這塊小市場來? 然後美其名是保護智慧財產權? 這是哪個少根筋的人想出來的主意呢???

這是一個全球化的時代,台灣所有的產品(不管實體產品或文化產品)都要靠外銷,都要想辦法賺到外國人的錢,才能夠在這個時代中存活。只靠政府保護(還要犧牲掉台灣人連上國外網站的權利)才有辦法存活的廠商,非得賺台灣這一個小島上的人民的錢,才能夠生存下來的公司,真的在全球上有競爭力嗎? 真的有必要附上這個(犧牲台灣網路自由)的代價,動用這樣的手段,去做這樣的智慧財產保護嗎?

政府要幫上這些智慧財產所有權人的忙,應該是花更多的力氣去幫這些廠商做全球行銷,讓全世界台灣以外的那99%的人,喜歡且更方便的購買台灣的產品。沒辦法做到這些,只能反過來限制自家人民的權益,政府單位做到這種程度,真的還有存在的價值嗎?

因為國外廠商建立的平台,讓我們寫的App可以在全球市場賣,對於讓我們的App能夠跨上全球舞台,在國際上行銷,台灣政府有幫上哪一點忙? 報告,實在是少的可憐!!! (偶而可能還扯扯後腿,造成廠商收款上的困難)

我當然也不喜歡自己的產品被盜版,我們也不喜歡某些地區的人總是連0.99美元也不花就破解和盜版App,但如果哪一天政府跟我說,要保護我寫的App在台灣的銷售權益,所以好心的幫我封鎖國外某些特定的App盜版下載網站,讓台灣人都上不去...呵呵(冷笑),我只會說你省省吧,我一點都不會感激政府,因為全球其他 99% 的市場如果都可以下載破解版,賺台灣這一點零頭你以為真有什麼意義嗎? (而且很可能因為被封鎖,我在台灣還傻傻的不知道自己的產品已經在國外網站上被盜版了咧,這整個不是蠢到極點嗎?)

防止盜版的事情,不用政府多費心,我們廠商自己做就可以了,那麼積極的拿公權力去封鎖特定的網站,只會讓大家覺得是不是因為政府受到特定廠商、財團、甚至特定國家的壓力,因此才想要以這種粗糙的手段保護特定人的權益?

甚至讓人覺得政府是否是在為以後更積極的管理手段而鋪路? 因為誰都知道只封閉台灣這一塊小市場的自由,所能對廠商的保護是相當有限的。不需要由政府少數人幫人民決定哪一個網站可以看,哪一個網站不能看。這一步是封鎖不讓你看特定網站,下一步就是你翻牆去看就說你違法...再下一步就是只要你看政府不允許你看的內容就是違法...如果真的這麼幹,這不就是網路白色恐怖嗎?

我姑且天真的相信智慧局真的是一片好意,但我也真的希望政府單位們都別再瞎忙了,快回頭幹點其他的正事吧...

ref:

搞台版 GFW、封鎖網站是侵權違憲!國外盜版網站抓不到?懶惰無能的政府才是幫凶!

 

 

 

2013年5月4日 星期六

[研討會]微軟實戰課程日 Demo影片與Slide

今天是有史以來第一次公開舉辦的MVP Open Day 微軟實戰課程日,整個議程非常的精彩,除了早上的座談之外,下午有十多堂的分堂課程,由不同領域的MVP,為參與盛會的朋友們介紹自己熟悉的技術。


這種盛會不僅僅是破天荒第一次,在台灣也是除了付費參加的TechDay之外,少數能夠聚集這麼多各領域不同講師的場合。

很高興有機會在今天和大家一起分享 雲端 與 行動裝置 的應用,相關的影片與Slides,可從底下位置下載。

[Slide] slides中多出來的內容是由於研討會上肯定沒有時間講完,因此把相關的要點整理出來提供學員們參考。

由於時間的關係,實在沒有辦法好好的完整介紹整個Azure Mobile Service,對我來說是一個遺憾。不過底下的影片中所展示的,透過Mobile Service來快速的為企業設計出一套工作分派系統,橫跨Web、Win8App、WP8App(如果你想要,也可以用iOS或Android),並且可以讓開發人員大幅減少撰寫服務的負擔,是未來值得一看的雲端應用服務。

影片:透過Azure Mobile Service設計工作分派系統
 
課堂中的DEMO使用到的背景技術,可以參考這邊

2013年5月3日 星期五

[研討會] MentroTrust集英信誠 資料庫與.NET開發技術論壇


很開心受邀在集英信成年度舉辦的研討會中,和大家分享雲端與行動裝置整合的議題,今天和大夥聊的很開心,期待有機會再和大家分享最新的技術心得。

Windows Azure相關的resource可以在底下網址找到:

Free Trial Link: 
 
課堂中的DEMO使用到的背景技術,可以參考這邊

2013年4月27日 星期六

[研討會] GAWB 2013 Hands on lab slides & video

今天下午微軟在UUU舉辦了與全球同步GAWB Bootcamp,底下是我負責擔任講員的Slides以及Hands On Lab操作影片~

Slide

底下影片均可放大用HD方式瀏覽,請自行切換為HD模式放大觀賞。

Exercise 1:使用Azure Mobile Services - Data
 

Exercise 1.1:Azure Mobile Services – Dynamic Schema

Exercise 2:使用Azure Mobile Services - Push

Exercise 3:使用Azure Mobile Services - Scheduler

Exercise 4:使用Azure Mobile Services - Auth



2013年1月28日 星期一

1/28 資策會上手營

1/28 資策會上手營 如何將Web移到Cloud (WebRole, Webiste, VM)

相關投影片與教育訓練影片如下:
投影片:下載
快速的建立Azure Web Site,將網站移轉上雲端,參考這裡

2013年1月16日 星期三

[課程] Windows Phone 8開發上手營

還沒寫過WP8的App嗎? 或是想跨入XAML, Windows Phone的開發卻不知道該如何上手? 又有免費的課程可以報名囉...  [報名位置]