2008年4月28日 星期一

Heros Happen { Here } -- 2008 announcing


  今天一整天參加了微軟 Windows Server 2008 & VisualStudio 2008 的聯合上市發表會。這是個規模媲美要收幾千塊門票錢的 TechEd 的免費大型活動,看到微軟現場所動用的資源,可見這兩個組合真是微軟的心肝寶貝。

    照例, 早上 Session Openning 一樣有精心拍攝不輸美國影集製作水準的宣傳廣告片,以及話劇演出。

  每次看到這些,就會興起我幻想的念頭,將來我自己開的公司也要搞這些宣傳影片...。看來也許我跟李安一樣鍾愛的是拍電影、而不是寫程式做軟體。

  縱然我從小就是喝微軟的奶水長大的,但心底總是對其他平台與技術心生嚮往,例如,Java & Linux。總希望有朝一日可以脫離微軟的束縛,我想那應該是件很有成就感的事。

  但是看過這次微軟這兩款與我工作高度相關的重量級產品發表會,我越來越不能堅定這個願望。

  加上這次透露今年九月後,微軟將會模仿當年 JavaApplet 的做法,推出真正可以跨平台、可以依附相容在所有各家瀏覽器的 mini CLR engine。這個重要的宣示意義,代表日後我們都可以直接使用原生的 .NET 語言來開發各種平台瀏覽器端的應用程式,如果這個願望成真,不但從此擺脫不同瀏覽器對 JavaScript 支援度不一致的惡夢,且可以在一個舒適一致的環境下盡情高速開發所有的網際網路應用程式,最重要的是,各個不同的作業系統,甚至 Linux 上都可以執行我使用 .NET 開發的軟體。

  有這樣的願景,更加動搖我原本打算學習 Java 的想法 ( 因為當初就是為了跨平台 )。

  當然,這種仿 JApplet 的做法所使用的 mini CLR engine,應該能做的事情程度不會超過 .NET Compact Framework 就是了。

  另外關於 Visual Studio 2008,算是把 VS 2005 成熟化,基本上令人驚艷的東西都和 VS 2005 差不多,只是搭配 .NET 3.5 把原本需要另外下載的 Libraries 變成內建功能。

  不過整合 TeamSystem 的專案管理 Feature 的開發環境真的還是非常吸引人呢!

2008年4月15日 星期二

黑傑克捉鬼記


        趁今天結束之前,趕緊補一篇湊數的文章 ^_^。

        上回談到程式鬼打牆,測不準原理,這一篇就讓我來用淺顯易懂的白話文來抓鬼揭秘吧。


        其實程式會出現這樣結果不一致的落差,來自於 Performance 考量的思維 --


        只要當你真正要看運算結果的時後才進行運算,否則你只是要我運算,我還是可以先偷懶擺爛。

2008年4月7日 星期一

程式鬼打牆,海森堡測不準原理

  最近這兩天都遇到鬼打牆事件,明明預估很簡單輕鬆,可以提早下班的工作,卻連兩天都遇到當場傻眼無法解釋的現象,弄到加班都差點搞不定。

  其實軟體開發就像是堆疊黑盒子的積木,你很難確定一個函式呼叫後,底層到底是怎樣運作才生出你所渴望的回傳值?

  今天我遇到一個鬼打牆的狀態,那現象就像是你要學生背英文單字,要求他邊寫邊大聲地唸出來。你看他唸得字正腔圓,紙上書寫的單字也拼得正確極了,於是乎你放心的說:這些單字你都會了,默寫就好,不用唸出聲。但結果你回頭檢查紙上默寫的單字,卻每個全都拼錯!?

  大驚之下,你又要求學生邊寫邊唸,結果又是全都正確,但是等下默寫又全拼錯了...。

  如果你是老師,八成這時候已經認定這個學生性格乖戾在惡搞你,恨得心癢癢拿起教鞭痛扁這劣徒一頓。但是,我這次所遇到的這個學生,卻是一支 .NET Framework 標準 Class Library 內的標準 API。

  上面寫的,是給不懂程式開發的朋友理解我所遇到的鬼打牆狀況。這種現象,像極了我物理界背景的朋友耳熟能詳的量子物理現象,測不準原理。

  先聲明,這是一個單一處理程序與單一執行緒簡單到不行的程式。

  整件事就是開發時期,為了仔細觀察資料的變化,我會不斷把資料每個步驟後的狀態都輸出到螢幕上 ( Debug.WriteLine( ... ) ),確定他的變化如我預期。等到確定資料的每個狀態都正確後,我唯一做的事情就是把輸出到螢幕上的程式全部移除,交給客戶測試。沒想到資料結果怎麼測怎麼錯,連我自己機器上也跑不出正常預期的結果,我在客戶面前簡直是傻眼變成張口結舌的阿呆,五分鐘前那句我都測過,絕對沒問題。無疑是當場賞兩巴掌讓我信用破產。

  我不敢吭聲地趕緊把剛剛移掉的那些用來把資料輸出到螢幕上的程式復原回來 ( 就只是單純的把註解掉的 Debug.WriteLine( ... ) 回復,絕沒有更多多餘的動作 ),準備開始除錯找出問題,結果一切又都正常了。

  「可能我剛剛版本更新沒有成功吧?我心想,然後又把那些輸出螢幕的程式移掉再更新一次,靠!程式一跑資料又全錯?

  這件事真的是反反覆覆搞了我快一小時那麼久,客戶在旁看我這跳樑的小丑都快打嗑睡了。當然,這件事我最後找出可以理解的原因,也避開了這個問題,不過理解原因後,不免要對微軟的 .NET Framework 的 API 不夠直覺的設計缺失感到不悅。

  如果大家對這個程式的測不準原理的現象感到好奇想體驗,我提供以下的程式碼讓有興趣的人玩玩,至於造成此現象的原因,就留給大家自行參透吧 (或我下次在撰文解答 ):

  程式說明:這是一個處理以下 XML 文檔的簡單程式,

  <Root>
    <A/>
    <B>
      <BB/>
      <BB/>
    </B>
  </Root>

  程式要取出所有 <BB></BB> 內的資料,並且從整份 XML 內移除 <B></B> 節點 ( XmlNode )。

  Code (.Net 1.1 & C#):




string sXml = "<Root><A/><B><BB/><BB/></B></Root>";

XmlDocument oDoc = new XmlDocument();

oDoc.LoadXml(sXml);

// 關鍵來了

XmlNodeList oBBNodes = oDoc.SelectNodes("//Root/B/BB");

// Debug.WriteLine("oBBNodes.Count=" + oBBNodes.Count);

XmlNode oBNode = oDoc.SelectSingleNode("//Root/B");

if (null != oBNode) oDoc.DocumentElement.Remove(oBNode);    // 從原本的 XML 文件中拔除 <B></B> 以下的整個節點

Debug.WriteLine("oBBNodes.Count=" + oBBNodes.Count);




  這樣你就可以看到這懸疑的現象了。oBBNodes 明明就應該有兩個節點 ( Count=2 ),但是執行以上的程式,螢幕上卻會得到 "oBBNodes.Count=0" 的答案。

  但是如果把第六行的 // Debug.Wr..... 的註解恢復成可執行的 Code,結果螢幕上跑出來的輸出卻是:

   oBBNodes.Count=2
   oBBNodes.Count=2

  螢幕重複兩次輸出,但都是正確答案。

  哈,真的是很像測不準吧。如果不想跑出第六行的螢幕輸出,卻又想呈現最後正確的結果,可以把原本第六行的程式改成 "int n = oBBNodes.Count;" 做個愚蠢的虛功即可。

  真的是一整個蠢到不行。