1. 重生的 IBM ThinkPad X40 ...

    我自己用了快六年的 ThinkPad x31 掛掉了,又沒潑到水,送去 LENOVO 修理,就回我 "液體入侵" ... 換主機板要 NTD 26500 ... 錢太多才會修,因此就跟我姊ㄠ了她已經沒在用的 ThinkPad x40 來用用...

    X40 什麼都好,就是敗在它那顆 Hitachi 1.8" HDD 效能實在太爛... 拿到 X40 後就馬上重灌 XP,剛灌好後就用 HDTune 測一下這顆硬碟的鳥效能..

    HDTune_Benchmark_HITACHI_DK13FA-40B

     

    後來也很巧,經過一夜灌了堆必要的軟體跟工具之後,突然喀啦一聲,硬碟就再也不能用了 :~  上網找找有無硬碟可以買? 還真慘... 都是拆機或是二手,個人保固七天或是一個月的那種。Hitachi也停產了,除了容量有 60GB 的之外也沒別的選擇了。效能很鳥的硬碟,相對的 $$ 也不算便宜,害我考慮了半天...

    後來決定用 CF -> IDE 的轉卡,加上忍痛買了張 SanDisk Extreme IV 8GB CF 卡,也就是俗稱 "偽SSD" 的解決方案,裝好後好像完全換了台電腦似的,剛裝好的 XP PRO (原版光碟安裝的,沒有刪掉一堆內建的軟體跟服務),開機的 WINDOWS 光棒,跑不到一輪就進 WINDOWS 了 @_@,真是傻眼,效能的增進遠超過我的預期...

    雖然容量小了點,不過效能跟原本的 1.8" HDD 實在差太多了,不足的容量就再補張 16GB SD 卡撐著用。只要不裝啥大型檔案,一般的 OFFICE 文件還不成問題,用起來也還不錯! 原本慢到想扔掉的 X40 就這樣又活了過來 :D

     

    最後補上 SanDisk Extreme IV 8GB 的效能測試圖:

    HDTune_Benchmark_SanDisk SDCFX4-8192

    2008/11/06 敗家 有的沒的

  2. [RUN! PC] 2008 十一月號

    IMG_0208

    YA! 第四篇!! :D 還是一樣要先感謝一下編輯賞光,讓我有點空間寫些不一樣的東西。

     

    基本的執行緒相關的程式設計跟函式庫,講的差不多了,其實這些也沒什麼好寫的。接下來打算寫一些應用的模式,來談談有那些方法,那些設計方式才能夠有效的發揮多執行緒的優點。看了 .NET Framework 4.0 / Visual Studio 2010 的 ROADMAP,有一大部份的重點擺在平行處理,INTEL年底也要發表四核 + HT 的 CPU ( WINDOWS 會認為有八個處理器 ),軟硬體都備齊了,剩下的就是程式設計師的巧思了。

     

    其實之前貼過幾篇類似主題的文章,只是這次把它統合起來介紹一下。生產線模式,如果簡化後就是 [生產者消費者] 的模式,而把它徹底一點的應用,則是上回提到 [Stream Pipeline] ..

    這篇也是第一次在雜誌上嘗試說明比較偏設計概念的文章,實作比較少,很怕不合讀者的口味... 應該不會貼了就沒續篇了吧? :P 有買雜誌的記得讀者回函填一下,哈哈,也算是點鼓勵。這次範例程式也是 Console application (我不會寫太炫的程式 :P ),需要的可以點 [這裡] 下載!

    2008/11/04 RUN! PC 專欄文章 .NET RUN! PC 作品集 多執行緒 技術隨筆

  3. 該如何學好 "寫程式" #5. 善用 TRACE / ASSERT

    哈哈,這篇拖的夠久了 :P 上篇扯太多,寫到一半寫不完就留到這篇了。寫出可靠的程式,這是軟體工程師的基本要求。上篇提到了 TRACE / ASSERT 的應用,來複習一下: TRACE: 原本是 C 的除錯用巨集,目的是用適合的方式輸出除錯用的訊息,用來跟一般的訊息輸出有所區別。因為用的是不同的方式輸出,可以很容易的統一關掉。隨著工具的進步,輸出的方式也越來越適合除錯,比如輸出到開發工具的除錯視窗,或是輸出成記錄檔等等。 ASSERT: 也是除錯用巨集,它接受一個 bool 參數,輸入值為 TRUE 時一切正常,就像沒呼叫一樣,輸入 FALSE 則會中斷程式,或是輸出顯目的警告訊息。目的在於確保程式的每個步驟情況都如預料般的順利。 這兩個東西從 C 的巨集,衍生出各種語言及環境都有各自的版本。它的目的很簡單,就是 [Writing Solid Code] 裡提到的: 用同一套程式碼,同時維護兩個版本 (RELEASE / DEBUG),讓錯誤自動跑出來   雖然這本書提到了不少技巧,正確的應用 TRACE / ASSERT 是最基本的。但是那些細節並不是主要的重點。重點是你在寫 CODE 時有時時刻刻記得要盡量減少 BUG 嗎? 你有正確的擬出對策嗎? 來看看上回最後一段範例程式:  

    加上 ASSERT 的算分程式碼[copy code]
    public static int ComputeQuestionScore(XmlElement quiz_question, XmlElement paper_question)
    {
        int totalScore = 0;
        int itemCount = quiz_question.SelectNodes("item").Count;
        Trace.Assert(quiz_question != null);
        Trace.Assert(paper_question != null);
        Trace.Assert(paper_question.SelectNodes("item").Count == quiz_question.SelectNodes("item").Count);
        //
        //  如果都沒作答, 此題放棄
        //
        if (paper_question.SelectNodes("item[@checked='true']").Count == 0)
        {
            return 0;
        }
        //
        //  題目的配分
        //
        int quiz_score = int.Parse(quiz_question.GetAttribute("score"));
        //
        //  答對一個選項的分數
        //
        int item_score = quiz_score / itemCount;
        for (int itemPos = 0; itemPos < itemCount; itemPos++)
        {
            XmlElement quiz_item = quiz_question.SelectNodes("item")[itemPos] as XmlElement;
            XmlElement paper_item = paper_question.SelectNodes("item")[itemPos] as XmlElement;
            //
            //  算成積
            //
            if (quiz_item.GetAttribute("correct") == paper_item.GetAttribute("checked"))
            {
                totalScore += item_score;
            }
            else
            {
                totalScore -= item_score;
            }
        }
        Trace.Assert(totalScore >= (0 - quiz_score));
        Trace.Assert(totalScore <= quiz_score);
        return totalScore;
    }
      各位仔細看一下加上 ASSERT 的地方。大家寫程式,通常都是腦袋裡想著 "我要處理什麼問題" ,很少人會去想錯誤處理的部份。沒錯,這部份的確是吃力不討好,以此例來說,光是傳進來的參數就有可能狀況百出了。正常的流程都寫不完了,誰還有力氣去把這些錯誤都擋下來? 不過最容易出錯的地方也在這裡。我常在跟其它工程師說,正確的資料 (參數) 傳進來,本來就應該有正確的答案傳出去。難的是錯誤的資料傳進來,你還得回應 "正確" 的錯誤訊息回去,這才真的是個挑戰。這時 ASSERT 的效果就出來了。你可以把 ASSERT 想像成 "宣告" 的子句。以 line 5 ~ 7 行為例:
    確保傳入參數是正確的[copy code]
    Trace.Assert(quiz_question != null);
    Trace.Assert(paper_question != null);
    Trace.Assert(paper_question.SelectNodes("item").Count == quiz_question.SelectNodes("item").Count);
    
      這三行看在我眼裡,意思就是: "這兩個參數不能是 NULL,而且兩個 XML ELEMENT 都要有一樣數量的子節點 (Element),否則就不惜代價警告我" 同樣的,在程式的中間,還有傳回值之前,也都可以用同樣的方式來替你的程式 "把關"。再來看看算完成績後,要把值傳回去之前的 CODE:
    確保傳回值的範圍正確的程式碼[copy code]
    Trace.Assert(totalScore >= (0 - quiz_score));
    Trace.Assert(totalScore <= quiz_score);
    return totalScore;
    
      這兩行的意思就是: "不管成績怎麼算,每張答案卷最後的總分一定介於 0 ~ 滿分之間。一樣,有例外的話就不惜代價警告我"   聽起來蠻狠的,不惜代價...,不過使用 ASSERT 的話就真的是這樣。通常碰到 ASSERT 後,程式不是進 DEBUGGER 就是直接關掉了。不過請大家注意一下,並不是到處加上 ASSERT 你的程式就沒問題了。要搞清楚加上它的目的是什麼。它要抓的是你程式的 BUG,不是執行期的錯誤 (比如 USER 輸入錯誤的值,或是必填的資料沒填等等)。執行期的錯誤,你還是得乖乖的寫程式,不能用 ASSERT 替代。 舉例來說,如果最後算出來的分數是負的,則會觸動 return 前的 ASSERT。有些有點經驗又有點兩光的 PROGRAMMER 可能會自己顯示一些錯誤訊息。但是這跟本不干 USER 的事啊! 會出現這種情況,錯的一定是 "程式" 本身,也就是你看到 ASSERT 警告後就該來改程式抓 BUG 了。加上 ASSERT 的目的就是在你的程式到處布下眼線,任何一個地方偵測到不對勁,馬上通知你來處理。 當你有心把程式寫好時,你才會覺的這樣作是必要的,而不是累贅。你眼線布的越多,BUG就越難藏在你的程式裡。相對的,如果傳進來的參數就不對了,那應該怎麼辦? 這時就要小心分清楚你要抓的是 BUG 還是做錯誤處理了。如果參數是 USER 直接輸入的,那收到 NULL 或是錯誤的值本來就有可能 (吃芝蔴那有不掉燒餅的...),你需要的是老老實實寫好錯誤處理的流程。但是如果你的 API 早已嚴格定義不接受 NULL,卻還是有白目的工程師硬把 NULL 傳給你的 API,那這時就是 BUG 了,應該用 ASSERT 抓出來,然後找到冤大頭叫他改程式。 不過這樣的 CODE 可不能交到 USER 手上。想像一下如果你正在用 WORD 打文件,結果碰到一個小 BUG,ASSERT 就跳出警告訊息要中止程式,你連存檔都來不及,大概會抓狂吧。這時就是一份程式碼兩種版本的作法發威的地方了。交給 USER 的程式,就應該是切到 RELEASE MODE (或是關掉 ASSERT / TRACE) 編譯的版本。這時所有的 TRACE / ASSERT 好像完全消失一樣,程式就如同一般情況運作。 當 USER 回報一些很難抓到的 BUG 時,這時就可以打開 ASSERT 或是改用 DEBUG BUILD 的版本,再讓 USER 去重現 BUG,這時如果你都有老老實實加上 ASSERT 的話,BINGO,問題在那就一目了然。看看是那一道 ASSERT 指令被觸發,就知道是什麼問題了。抓 BUG 最麻煩的就是找出錯在那裡,而善用 ASSERT 就可以讓 BUG 自己跳出來告訴你出了什麼問題,只要你養成好習慣。   再舉一個應用例。看到 Steve Maguire 先生舉這個例子,真是想拍手叫好。他舉了他們在開發 EXCEL 時的例子。EXCEL就是要替試算表作一堆運算,當年還在 DOS 時代,CPU怎樣都不夠快,RAM怎樣都不夠多,程式設計師無不絞盡腦汁,要榨出所有的運算能力,最佳化做到無所不用其極的地步。不過這種東西是錯不得的啊,少算了一塊錢還得了? 碰到這種問題你該怎麼辦? 通常,我們都會先有個安全的版本,算的不快,但是因為邏輯簡單,比較不容易出錯。這種版本寫出來後才開始想盡辦法,去改善程式讓速度加快。馬先生 (ㄜ... 是馬奎爾先生... ) 就充份應用了 ASSERT,隨時都要把 BUG 逼出來的精神,真的把 "驗算" 的方法應用上來。它的作法很簡單,同一張試算表,用兩份不同的程式碼各計算一次,最後再來比對一下結果 (驗算)。只要兩者得到的答案不一樣,那就是出問題了! 當然也有可能是安全的版本寫錯了,不過你至少多了個機會抓到問題,因為不一樣的話,一定 "至少" 有一邊是錯的!   沒有這樣的前題的話,各位看到可能都會在心裡想: "有沒有搞錯,程式都寫不完了,還要寫兩種演算法來驗算?? 老闆又不會多給我一點薪水..." 沒錯,這的確是成本較高的方法,每套系統應該都有關鑑的地方,只要有絕對不能失誤的地方,就值得用這種作法。速度的問題怎麼辦? 很簡單。你只要在 DEBUG MODE 才啟用這 "驗算" 的機制,測試人員輸入各種數值做黑箱測試,如果每次測試的過程中發現驗算錯誤,則 "黑箱" 測試就能幫助你抓到只有 "白箱" 測試才有可能抓到的 BUG !   我寫的這個範例程式 (算成績) 其實也準備了兩個版本。上一篇貼的是基本的作法,結果比較可靠。而為了效率我也寫了另一份程式碼,用的是位元運算,希望藉著位元運算,一次就把多選題的答案給算出來。開發的過程中就用了 ASSERT + 驗算的技巧,它不會加快我寫程式的速度,但是它可以加速我找到 BUG 跟解決 BUG 的時間!   有沒有覺的這跟單元測試其實很像? 沒錯。單元測試就是一樣的觀念演變出來的作法,所以你用的單元測試 FRAMEWORK 也延用一樣的 ASSERT 使用慣例。你會發現其實之間的觀念都是相通的,只不過單元測試更進一步的把它系統化了,由原本四處藏在程式碼中的 ASSERT,抽出來成為一個一個獨立的 TEST CASE,由原本被動的執行時期檢查,演變為主動執行所有測試的 UNIT TEST。我覺的 Kent 在 XP (extreme programming) 裡舉了一個例子來說明單元測試,比喻的很貼切,我覺的也一樣能拿來比喻 ASSERT:   "車子裝了煞車,是要讓車子能開的更快!"   聽起來好像很蠢? 煞車明明是讓車子停下來的... 其實不然。想像一下如果你的車子沒煞車,你敢開多快? 了不起就是撞到不會怎麼樣的速度,或是油門放開就停下來的程度而以。有了煞車讓你有信心,碰到危險時你隨時能把車子停下來,你才敢把車子開上高速公路...   很有道理的比喻,ASSERT 跟 UNIT TEST 大部份人都覺的是 "煞車",是拖慢你速度用的,但是也因為有這些 "煞車",你才能放心的衝更快。當你有充份運用 ASSERT 的話,你就能很放心的寫程式,沒有後顧之憂。其實類似的關念,Steve Maguire 的書還有提到很多,只不過它的範例都是用 C 寫的 (還不是 C++ ...),看起來會吃力一點。範例程式可能對現今大部份的人都用不到,但是裡面的觀念跟作法還是很有參考價值的,手上還有這本書的人不妨拿起來翻一翻。   講到這裡,花了兩篇才講完第一個部份,主要的重點就是用 TRACE / ASSERT 來說明,要讓你的程式夠穩定,第一個要改進的就是你寫程式的想法,觀念及態度。各位不妨以這兩篇的例子,自己回想看看,你做到那幾項:
    1. 你寫程式有考慮到這些問題嗎?
    2. 如果你寫程式有用這些方法,有多少你曾解過的棘手 BUG 會變的迎刃而解的?
    3. 加上 ASSERT 之後,你是否對你程式更有信心了?
    4. 你是否更認同單元測試的必要了?
      想法跟觀念有了改變,才有可能開發出優良的軟體。你開始認同這樣的想法了嗎? 恭喜你,你已經跨出第一步了。不過光是 BUG FREE 還不足以成為優秀的軟體工程師,這只是必要條件之一而以。除了把程式寫的 "可靠" 之外,接下來的挑戰是如何把程式寫的 "漂亮" ? 下回要開始來探討如何構思你程式碼的結構。什麼樣的結構,什麼樣的方式去分析你的問題,才寫的出架構漂亮的程式? 別急,請期待續篇 :D     -- 註: 範例程式很多 CODE 被我跳過去了,有興趣的人可以抓回去研究看看... 請點 [這裡] 下載。

    2008/11/03 系列文章: 如何學好寫程式 .NET C# 作品集 專欄 技術隨筆 有的沒的 物件導向

  4. 也是 "生產者 & 消費者" ...

    IMG_3467 (Canon PowerShot G9)

    哈哈,貼一下家裡魚缸的照片... 家裡養的孔雀魚一直生就算了,無意間丟進來的一隻蝸牛,沒兩個月竟然也生了一堆,現在算算大概有四十隻吧 @_@,照片裡紅紅的都是...

    不過有了蝸牛 (消費者),把水裡的魚大便跟水藻都吃的乾乾淨淨的也不錯啦,以前每週要換一次水,現在偷懶撐久一點都無所謂了 :D

    2008/11/01 有的沒的

  5. 關不掉的 Vista UAC !?

    不知道是更新了啥 PATCH,還是那次沒正常關機,我公司 VISTA 的 UAC 突然莫名奇妙的被打開了。怪的是控制台裡看到的還是關掉的,不管怎麼改狀態也不會改變 (一直都是關的) ...。

    直覺告訴我一定是控制台的 AP 那邊出問題,設定值寫不進去造成的...,於是我就開使找其它可以修改 UAC 設定的方法...,最後找到這個,還真的成功了 :D,看來沒機會動用 ProcessMonitor 追追看問題了..

    找到的方法是: msconfig.exe

    在開始 --> 執行裡輸入 msconfig.exe 後,可以看到這一項:

    image

     

    看來是直接修改 registry, 果然有效,直接執行後 REBOOT 就一切正常了 -_-, 如果有人也碰過一樣的問題可以試看看!

    2008/10/31 Tips