2009年4月27日

自製無用小工具系列 - 利用 Excel VBA 產生大量亂數日期

這個工具起因於某日,坎尼要建立測試資料,但日期必須打散
極度懶惰的坎尼就用 Excel 做了個亂數跑日期的小程式

「為什麼要用 Excel 哩?」『簡單、好用、又好玩』

第一、要產生某種格式的資料很快很簡單
第二、啟動不像 visual studio 那麼久
第三、不用再重新拉UI,每個儲存格都是 TextBox

要寫 VBA 之前,先知道 VBA 編輯器要怎麼開啟,見下圖
(快速鍵為 ALT + F11)

再來是原始資料的創建
先全選 Sheet1 的儲存格,右鍵選儲存格內容,將儲存格轉換為文字格式
A1儲存格輸入 1995,B1輸入01,C1輸入01
再利用 Excel 的自動填滿選項功能建立如下圖的資料 (這時候就知道Excel的好用了)

接著一樣把 Sheet2所有的儲存格改為文字格式
以免產生出來的資料,Excel會自以為聰明的幫你改格式 :D

資料準備好之後,就按下 ALT + F11 進入 VBA 編輯器
再來就是寫程式了,當然,是要用 VB 的語法

下圖先用兩個 For 迴圈決定要產生的資料量 (I、J分別為 Column及Row)
新增三個亂數值,分別決定年月日的亂數 Index
再將亂數產生的值組合起來放進 Sheet2 的儲存格裡

寫完程式之後,直接點執行鍵即可 (編輯器上面的綠三角形)
再切到Sheet2就可以看到滿滿的亂數日期了


Excel 檔下載 (若要使用坎尼的檔案,記得打開巨集)

其實這個程式把Sheet1的資料來源改一改 (亂數index的range也可以更改)
就可以變成 電影名稱產生器武功名稱產生器...

最後補充一下,坎尼程式裡年的 index 亂數設錯了 (應該為 14)
所以不會有 2007 及 2008 年的資料

2009年4月19日

微軟內部開始實驗的新 QA 機制:Bug Goal

這個月初去微軟位於南港的創新中心(Microsoft Innovation Center, MIC)上課,
在第三天的課程中聽到一個很有趣的觀念,叫做 Bug Goal,以下就來說說這是什麼。

在上一篇文章:微軟的組織架構 & Developer 的工作態度中曾經提到,基本上每個微軟的 team 都是由 PM、dev、以及 tester 組成,而 Bug Goal 就是由 Tester 這邊提出來的新觀念,目前正在美國總部小規模實驗中,如果成效良好,可能會全面推廣。

顧名思義,Bug Goal 指的是 bug 的指標,更清楚一點的說,是指在每個功能區塊中預期會產生多少 bug。一開始聽到這個觀念大家都覺得不可思議,所以花了不少時間討論。

Bug Goal 一開始大概只能靠 manager 從過去的經驗中做一個接近直覺的估計,但是隨著經驗的累積,理論上這個值應該愈來愈精準。訂定 Bug Goal 的目的如下:
  • 激勵 tester 在程式中找出數量足夠的、有意義的 bug,目標就是 Bug Goal 設定的數量。
  • 激勵 dev 寫出更高品質的 code,讓 tester 沒辦法抓出足夠的 bug 來達到 Bug Goal 設定的數量。
    (有點像是故意在 dev 和 tester 之間建立一個良性的競賽,目的在提高品質)
  • 讓 PM 多了一種衡量程式品質的數據,當某一個功能根據過去的經驗,是很容易產生大量的 bug,但專案執行一段時間以後 tester 卻幾乎沒有找到任何 bug 的時候,就應該主動更深入的了解一下專案執行的狀況,當然有可能是程式的品質真的非常好,但有沒有可能是 teser 在偷懶?或者 dev 偷偷把功能簡化,所以程式變得很簡單,不容易出錯?
會影響 Bug Goal 的因素包括:
  • 功能的複雜度
  • dev 的熟練度
  • tester 的熟練度
  • 需求變化的程度
  • ...(可能還有很多其他的因素,總之是要綜合考量這些因素)
有一點要強調的是,tester 找到的 bug count 有沒有 meet Bug Goal 絕對不是一個適合用來衡量 tester 能力的指標,例如 bug 的品質就是一項重要的因素(有沒有濫竽充數?),而有經驗的 tester 在 system design 的階段就會密切參與討論,貢獻自己的專業知識,提高系統的 testability,以及避免可能很難測試的設計,這些都可能造成 bug count 的降低,自然就達不到預先設定的 Bug Goal。

反過來說,達不到 Bug Goal 可以看成是一個好現象(前提是沒有人掩耳盜鈴),而且整個 team 長遠的目標應該是要讓 Bug Goal 越來越低,這表示 team member 的成熟度很高,可以產出高品質的 code。(這當然是個非常遙遠的理想)

2009年4月18日

[InfoQ QCon] 10 ways to improve our code

早上看了這個 talk (InfoQ Video link, Summary),主題是講 10 個改善程式碼品質的原則,有些不錯的地方值得記錄一下。

主講人 Neal Ford 先生是 ThoughtWorks 的架構師(跟 Martin Fowler 同一家公司),
演講的內容是從他寫的書:The Productive Programmer 裡面整理出來的,他講的很流暢,也蠻幽默的,演講時間大約一小時,投影片可以在這裡下載。

由於重點在 Summary 裡面都有列出來了,因此以下採用補充的形式記錄我印象深刻的部份,請搭配 Summary 服用。

Composed Method & SLAP (Single Level of Abstraction Principle)
Composed Method 這個原則講的是透過 method 的切割,盡可能的縮短每個 method 的行數,最後完整的 class 會由很多小小的 method 組成。

以切割 method 的方式來縮短行數的目的在於將程式碼的權責劃分清楚,以便達到最大程度的 reuse。但是在設計上也不應該為了切割而切割,此時可利用 SLAP 作為切割 method 時的 guideline。

SLAP 看來是 Neal 發明的縮寫,在 Wikipedia 上目前查不到,原始出處就是他寫的 The Productive Programmer,另外可以參考 Microsoft Architect Journal 2004 年 7 月號:Secrets of Great Architects(Levels of Abstraction: A Powerful Weapon for All Engineers)。

簡單的說,程式碼本來就是很抽象的,但還是可以區分出不同的抽象層次。最粗略的分法是,對 DB 的操作歸類為系統中較底層的程式碼,而 Domain Logic 則是系統的核心,UI 則是系統與使用者互動的介面,因此這三個層次的程式碼不應該混淆在同一個 method 中,就算不抽離到其他的 class 中,起碼也要拆解成不同的 method。

以下是同一個 method 中包含多個抽象層次的 pseudo code(節錄自投影片):
addOrder(WithMixedLevelOfAbstraction)

在這個未經 refactor 的版本中,可以看到非常詳細的操作 DB、Transaction 的程式碼,跟此 method 要處理的「新增訂單」Domain Logic 混雜在一起,因此閱讀的時候你的”心智”(mind)要多次在不同的抽象層次間的切換(mental shift),這種額外的負擔會造成閱讀程式碼時的不順暢。

以下是 refactor 之後的結果:
addOrder(WithSeparatedLevelOfAbstraction)

經過 refactor 後程式碼明顯縮短很多,而且現在此 method 中的抽象層次(大致)是一致的,如「completeTransaction」、「rollbackTransactionFor」等等的 method 不但名稱更有 business 上的意義,也隱藏了與 business 無關的、底層 API call(操作 DB、Transaction), 因此這段程式碼閱讀起來比上一個版本順暢很多,一行一行的順著讀下來比較接近日常生活的會話
(撰寫此 method 的目的:新增訂單)
  1. 建立所需的 DB Connection 和 SQL Statement。
  2. 開啟 Connection 和準備 SQL Statement。
  3. 設定 transaction 的狀態。
  4. 新增一筆訂單。
  5. 設定訂單號碼。
  6. 將購物車中的物品資料寫入訂單。
  7. 完成交易。
Question Authority
這個原則中文應該可以稱為「挑戰權威」吧!例如挑戰 coding convention,或者(公司內)常見的系統設計方式。Neal 舉的例子是一個有名的猴子實驗,我找到一篇文章:The Origin of Tradition: A Monkey Experiment (圖文說明),另外很久之前在書上看過一篇類似的文章,我自己打字以後做成 PDF 檔,可以在這裡下載(這都是文字,沒有圖,但是內容比較充實)。
比較有趣的是上面那篇我另外找的文章裡面有引述愛因斯坦的話:

Only two things are infinite, the universe and human stupidity, and I’m not sure about the former.
                                                                                               -Albert Einstein

建立 convention 對 productivity 是一件好事,但是深入的了解 convention 形成的原因,才有辦法在適當的時候打破 convention,以新的方法做事情,創造更大的價值!

詳細內容就不贅述了,不管這是真的實驗還是一個故事,總之很發人深省!

Use the Anti-Objects Pattern
在這裡 Neal 利用早年大型機台上的老遊戲 – Pac-Man(中譯:小精靈)來解釋何謂 Anti-Objects Pattern。在 Wikipedia 上有個 entry 就叫做 Antiobjects,剛好裡面就有講到 Pac-Man(警告!以下資訊可能會破壞你對小精靈這款遊戲美好的回憶 XD)
The notion of antiobjects is a computational metaphor useful to conceptualize and solve hard problems by swapping computational foreground and background.
If we implement, as part of a Pac-Man game, a ghost we are tempted to think of the necessary behavior associated with the ghost object.
Antiobjects turn things on their head. In the case of Pacman we put the main computation into the maze.
                                                                                                            - Wikipedia


在當年運算能力十分缺乏的平台上,是無法將「追逐小精靈」的 AI 設計到「鬼」這個 object 上的(由鬼來計算迷宮中的 shortest path ),因此反過來設計者把 AI 設計到迷宮的地板上去,並且提出一個 Pac-Man Scent(小精靈的氣味)的觀念,也就是目前小精靈所在的那塊地板氣味最強,而這個氣味是交由迷宮的地板來記錄的,當小精靈遠離這塊地板時,它的氣味就逐漸減弱。

因此鬼實際上沒辦法知道小精靈的位置,鬼都是漫無目的的瞎逛,若剛好踩到一段有小精靈氣味殘留的地板,才會一路往氣味更強的方向去「追殺」小精靈。

透過 antiobjects 可以簡化 AI 的設計,另外也是訓練你如何 think outside of the box 的好方法喔!

最後來回憶一下經典的小精靈遊戲畫面吧!
6

2009年4月14日

John Resig: The DOM is a Mess (and the inspiration I got from this talk)

這個 talk 約 1 小時 12 分,推薦給對 jQuery/JavaScript 有興趣的人,對於開發 Framework/API 的人來講也有很多可以借鏡的地方。(線上觀賞影片在這裡)

John Resig 是目前很紅的 Open Source JavaScript Library – jQuery 的發明人,
他任職於 Mozilla Corporation,這場 talk 是他分享在開發 jQuery 的過程中遇到的困難以及心得感想,對我來說蠻有啟發性的,雖然 scope 差了十萬八千里,但我維護的元件性質也類似 jQuery,也會被很多 client 以各種意想不到的方式使用,也要面對 backward compatibility、graceful degradation 等等問題。

以下是我聽到的一些重點:

Graceful Degradation


這裡有個定義,在 web browser 這個領域裡面,很常見的 reference 是 YUI Graded Browser Support

這個概念講的是由於實務上的限制(時間、金錢),(JavaScript) framework 沒辦法 support 快速變化的各家 browser 的各個版本(的各個 mode),因此要有一套 support 的策略,細節包括各家、各版 browser 的市佔率,以及要 support 所必須付出的成本(這通常跟 browser 遵守 standard 的程度成正比)等等。

除了要制定一套策略,程式的寫法也要注意,以下是從影片中節錄的圖(有點糊@@)
ResigSpeech_GracefulDegradation(EventBinding)

這裡的程式寫法的順序大有學問,首先在 if statement 裡面試圖用標準的 W3C 語法來附加 EventListener,但是並非所有 browser 都有實作 W3C Spec,因此針對 IE 這個尚未實作 W3C Spec 的 browser 的 API Call 就寫在 else if 裡面。

這樣有什麼好處呢?當未來 IE 實作了 W3C Spec 之後,這個 attachEvent function 的程式一行都不用改,IE 自然可以執行到 if statement 中的標準 W3C 語法!而遇到還沒實作 W3C Spec 的 browser 也還是可以正常的執行這個 function(只是經過額外的判斷,效能稍微差了一點點)。

結論就是:愈符合標準/愈新的 API Call 應該寫在越前面,vendor-specific 的 (non-standard_ API Call 應該要往後挪,如此才可減少未來升級的 effort。

Feature Simulation


接下來一個重點是如何判斷目前執行這段 js 的 browser 是否有提供特定功能?
 
最早的時候都是透過 browser sniffing/user agent sniffing 的技術,但是這樣的寫法太沒有彈性,每次 browser 推出新版的時候,程式可能都需要修改。甚至當網站被攻擊的時候,可能 header 中的資訊會被竄改(或者 power user 自己修改),導致 js 判斷錯誤,進而產生了奇怪的畫面等等。

比較好的程式寫法如下圖所示(還是有點糊@@)
ResigSpeech_FeatureSimulation(Verify API)


前半段的程式 create 了一個 div,然後在這個 div 上加上 comment,最後 return getElementByTagName(“*”) 的長度是否為零的 boolean 值。根據這個值就可以知道目前的 browser 對於 getElementByTagName 的 implementation 是否有 bug(一切以 W3C Spec 為準),而接下來的程式就可以根據這個 boolean 值做適當的處理。


這裡的觀念類似前面講的 Graceful Degradation,重點在於不要根據 browser/user agent 的版本來假設目前 browser 對某個 API (e.g., getElementByTagName) 的 implementation 為何,實際上用程式測出來的結果才是最準的!
(這也許可以算是 unit test 的進階/變形應用?)


Reduce the number of assumptions


這其實是比較一般性的通則,在程式裡面通常都會有很多假設(assumptions),
很多時候寫程式的人不會特別去注意這些假設,但是就如同去年 MS TechEd 的心得
當假設出了問題,或許是假設不符合實際情況,或者是被駭客攻破(e.g., 設法製造一個出乎你意料之外的 input),那麼系統就會出很大的問題。因此盡量設法減少系統中的假設是一個很好的 practice,系統的假設少了,出錯的機會就少(因為可能要多寫程式去處理一些特殊狀況)

但是適量的假設是有必要的,例如你很難(大概也沒有必要)對系統中每一個變數都額外再寫程式去驗證這個變數的 type 是否正確,這基本上是 type system 的工作,因此「type system 要負責抓到如 InvalidCastException 這樣的例外狀況,並停止程式的執行,以免程式真的 run 下去之後導致更嚴重的錯誤(buffer overflow?)」就是一個典型的假設,此時通常都需要信任這個 programming language 所提供的 infrastructure 是夠嚴謹的,而不是自己寫一大堆程式到處去做 type checking。

今天不知道為什麼突然想寫寫看這樣的心得,大概是因為最近類似影片看很多,
以後有空應該會多寫一點類似的文章 :p

2009年4月13日

The “I Suck” button in ASP.NET MVC Visual Studio Project Creation Dialog

上禮拜在看 Channel 9 一部請 ASP.NET MVC 的 PM – Phil Haack 現身說法的訪問中,
他提到了一個由 Scott Hanselman 發明的 private joke:The “I Suck” button.
 
到底這個 button 長什麼樣子呢?

當你安裝好 ASP.NET MVC V1 以後,安裝程式會順便安裝 VS 的 Project Template,
有趣的地方在於,當你 create 一個新的 ASP.NET MVC Application 之後,
VS 馬上會跳出一個詢問你是否要順便建立 unit test 專案的對話框:

ASP.NET MVC_WithUnitTestProject

上圖是系統的預設值,也就是微軟建議你應該順手建立一個 unit test 專案,
如果你 follow 了微軟的建議,那麼這時候螢幕上的就只是一般的「OK Button」。
(PS. Test Framework 不限定 VS Unit Test,也可以用 NUnit 等,作法參考這裡

但是若你選擇忽略微軟的建議,不要建立 unit test 專案,這時候畫面會像下圖這樣:

ASP.NET MVC_NoUnitTestProject

這時候原本的「OK Button」就變成「I Suck Button」了!

我覺得這個 private joke 某種程度上反應了微軟的 devs 對 unit testing 的看法,
也可以感受到他們樂在工作的感覺。可能某種程度也是要表達「MVC Pattern 本來就比較是合作 unit test」這個觀點吧。

接下來有空就來學一下 ASP.NET MVC 好了,順便練習 TDD!

2009年4月11日

[轉錄][合約]-保固期限的陷阱

這是在公司論壇看到的,偷偷轉出來 ... 雖然現在不需要處理這種問題,但還是可以多了解一下專案的各個層面。也許砍尼可以分享一些相關的心得 :p

========================= 以下是轉錄的內容 =============================

大家都知道,合約中的條款規定要特別注意。本專案開始訂定相關專案 RFP 及專案工作計畫時,有說明保固期限是一年;但在訂定合約時,因合約完成日期訂於年底(e.g. 2007/12/20),承辦人要求將保固期的說明寫成「自驗收合格日次日起,至次年十二月三十一日止,由廠商提供系統保固服務」,便於日後辦理計畫案之維護合約時,均可切齊到年底(一切是那麼的合情合理),當時未多加考量延遲驗收之風險而答應之。

專案進行後,因使用者驗證資料未依期望準時完成,故驗收拖至次年(e.g. 2008/1/5)才完成;保固期限原定至 2008/12/31 結束,但上述合約文件中的保固期文字為「自驗收合格日次日起,至次年十二月三十一日止」,故保固期限需依合約解釋至 2009/12/31 才結束,白白被多拗了一年。

以這個例子來看,如果能夠準時在該年年底(2007/12/31)前驗收完畢,保固期就只會算到 2008/12/31。但一旦超過 2007/12/31 才完成驗收,哪怕趕在 2008/1/1 當天驗收完畢,還是會被多拗一年的保固。日期切齊月底或年底是很自然的想法,所以這個要求可以理解。如果已努力過而客戶堅持要切齊,那就要特別注意結案的日期,推算一下最晚要在什麼時候驗收。從那個日期往前推 n 個工作天跑流程,以確保能在月底/年底前驗收完畢,避免發生類似的狀況發生。

========================= 以上是轉錄的內容 =============================

法律條文真的是很重要,莫名其妙的多扛了一年的保固,要付出的成本真是難以想像,
除了維護這個專案的成本以外,還有因為維護此專案而無法全力投入其他專案而產生的機會成本,還有對 team member 士氣的打擊,對 sales 的打擊 … 等等,實在是不可不慎阿!

2009年4月8日

自製無用小工具系列 - 格式化檔名

坎尼之前寫過 自製無用小工具 - part 1
沒想到這系列已經過了快半年了 (嚇)
但卻沒發半篇 囧

今天坎尼想要把檔案夾裡的檔名改成同一格式
ex. Img001.png、word002.doc...
一個一個改的話,幾千個檔案坎尼會改到臉抽筋吧
坎尼又懶的上網找工具

剛好想到以前寫過的副檔名更改小程式
於是坎尼花個二十分鐘做個小改寫

執行時,和之前的操作方式很像,先選擇路徑
接著格式設定完之後,就可進行更名動作
(這邊也還保有之前的副檔名更換功能)


執行成功之後
可以看到img資料夾裡的 png 檔都變成 IMG+流水號 的名稱
並且會新增一個 note 檔案,裡面記載更名前的對照表


程式的寫作流程基本上和改副檔名的那段差不多
利用 Directory.GetFiles 取得檔名
再替檔名換上新的格式及流水號,並記錄至對照表中
最後把對照表用 StreamWriter 輸出成文字檔

懶人更名小工具的 下載

這個工具目前不支援回復成原檔名的動作,所以使用前請三思
剛剛發現有點bug,明天修過後再補上新檔吧 :p

2009年4月6日

[軟體與現實生活的類比-1] 為什麼某些軟體只接受特定格式

有時候要跟完全沒有資訊背景的人(例如上一代的長輩們,或者是客戶!)解釋軟體如何運作是一件很困難的事情,我覺得一個很重要的原因就如同之前推薦的超長好文中的 Lessons From The Science of Nothing At All (Richard P. Gabriel) 中講的,因為軟體是極度抽象的東西,很多時候沒辦法直接對應到現實世界中大家習慣的事物,因此一般人很難理解資訊人員腦袋裡面到底裝了什麼東西,偶爾旁聽到資訊人員間的聊天內容,想必也覺得那根本就是火星話。

但其實如果仔細思考一下,還是有很多時候可以找到軟體跟現實世界之間的類比,
所以我打算慢慢把自己想出來的例子記錄下來,看看假以時日可以蒐集到多少 :D

Analogy 1: 軟體只能吃特定的檔案格式 <---> 車子加油的時候一定要加到油箱裡面

緣起:
上禮拜我老爸(沒錯,又是他)在整理數位相機的照片,問我說能不能把存在電腦裡面的照片存回去數位相機裡面,我說這當然 ok 阿,基本上記憶卡就跟硬碟是一樣的東西嘛。結果嘗試了一下,發現圖片檔的檔名要 follow 固定的格式,並且要放到指定的資料夾
才可以從相機裡面預覽,為了跟我老爸解釋這種「詭異」的現象,於是我想到一些類比。

首先,為什麼圖檔一定要放到指定的資料夾,否則相機就讀不到?這就跟車子加油的時候一定要把油加到油箱裡面是一樣的道理,如果你莫名其妙的把油加到水箱(把圖檔放到非指定的資料夾中),那麼不管加再多的油進水箱,油表絕對是顯示見底的。

再來,為什麼圖檔的檔名要 follow 固定的格式?突然發現這題沒有想到一個好的類比,等之後有緣想到再補

接下來討論為什麼每個軟體只能接受特定的格式。這就跟車子只能吃 92、95 或者 98 無鉛汽油一樣,雖然組成比例略有不同(e.g., word 檔的內容不同),但本質上都是汽油(格式都是 word),因為汽車的引擎就是設計要來吃汽油的,如果你無聊拿一桶蘋果汁倒進油箱,就算位置正確了,因為格式不對,車子是絕對不會跑的(e.g., word 沒辦法讀 powerpoint)
呼,第一篇就先寫到這裡吧,最近遇到一些問題,可以寫成另外一篇。我不知道練習這樣的思考對工作上會不會有很實質的幫助,但是如果在資訊人員之間偶爾也可以透過這種類比的方式來溝通,也許效果會比較好吧!

MS Chart Control 製作學生成績表

雖然坎尼在Chart Control出來時就裝好了元件,卻一直沒去測試這個新元件
另外看到很多blog都說摸索有點瓶頸
坎尼也不敢任意踏入無止盡的研究迴圈中...

最近有遇到要畫統計圖表的功能
加上 Tech. Days 聽了章立民老師的 ChartControl 線上研討會
於是放棄以前 OWC 的方式,用新的 Chart Control 來看看

元件安裝請參考保哥的 介紹好用元件:Microsoft Chart Controls for .NET 3.5
sample 檔一定要下載回來看,有很多 code 可參考

下圖是坎尼做的 sample -- 學生成績表
此表的特性為:
  • Y軸為自訂Label
  • X軸的學生名稱為直向
  • 長條圖上有分數顯示
  • 低於60分的人以紅色顯示成績條


這個表怎麼做的呢?
請先在頁面上放置個 Chart Control (如下圖)

接著用屬性 Panel 設定圖層的一些資料
但 Chart Control 可以用的屬性實在太多太雜了
坎尼也研究了半天才了解一些實用的屬性在哪設定
下圖為已經設定好的屬性 source code,下面會有解釋

Label 表示長條上要顯示的資料,#VAL表Y軸的值 (這邊是成績)

AxisY 為Y軸屬性,坎尼設定了 Maximum 為 100,表示最多顯示到 100
此項屬性不設定則 .NET 會自動控制 Y 軸的顯示值

接著是 CustomLabels,這邊自訂了 Y軸的標籤
這裡的重點是 ToPosition 屬性要設定,否則自訂標籤不會出現

AxisX 就是X軸屬性啦
這邊設定了 Interval=1,表示X軸上的所有標籤都會顯示
(預設為 Auto .NET會自動分配區間給 X 軸)
但 Label 的顯示會是橫向,自定義區間為1會造成標籤都擠在一起
待會兒坎尼會在後端的Code做點小處理

再來就是很重要的 DataBind 事件了

其實在 MS Chart Control 的論譠上有講到
要用 Chart 的第一步就是先 DataBind,看資料是否能正常顯示
再去設定顯示的樣式
坎尼為了容易理解,這裡就反過來講

可以看到 Chart 的 DataBind 方式不太一樣
給了第一個參數為 DataSource 接著是 x 及 y 軸的 DataMember
其實它也是可以支援
Chart1.DataSource = dt;
Chart1.DataBind();

DataBind之後就來處理顯示的樣式吧
剛剛有提到字會重疊在一起
於是坎尼把 X 軸的 Label 取出來加工,讓它變成直向
然後把 Y值小於60的長條變成紅色
如此一來,不及格的學生就一目瞭然
實際畫面會是第一張圖所顯示的那樣

其實 Code 不會寫很多
比較容易卡住的是一些前端屬性的設定
以後有空坎尼也來寫一下 Chart Control 的應用吧
大家有興趣可以上 MS Chart Control 的討論區

話說 snipping tool 的 highlighter 很好用
圖片中的黃底色都是用它來畫的

2009年4月5日

微軟的組織架構 & Developer 的工作態度

上週去 Microsoft Innovation Center (MIC, 在南港) 上課,第一天講的是 unit testing,
講師是 Bentham Chang (張濱顯),人蠻開朗的,上課的過程還蠻歡樂。其實關於 unit testing 的作法等等技術細節網路上資料很多,我比較有興趣的是他分享的在微軟工作的經驗,還有微軟的文化。

從 Developer (Dev) 的角度出發,工作上最直接相關的組織長得像下面這個樣子(接下來會大量使用到 Dev 這個 term):

MS_Dev_Map 
雖然我的圈圈畫的很醜,但我想表達的是在 MS 沒有上下階層的關係,三角形好像還是有個頂點:p 當然每種職位一定有 junior/senior 之分,也有各自的 Lead (e.g., Test Lead, Dev Lead)。


基本上從職稱就可以知道大略的工作內容(聽說很多美國公司也是採用類似的架構),PM 就是專案經理,Test(er) 在台灣常常叫 QA,Dev乍看之下好像是PG (Programmer)。

但是在台灣很多公司是 follow IBM Mainframe 時代的 terms,所以會有 PG/PA/SA/SD 等職位(很有 waterfall 的 fu),在上圖中看不出 PA(程式分析)、SA(系統分析)、SD(系統設計) 等職位,但是顯然這絕對不是說在微軟做軟體都不需要經過這些步驟。

我的感覺是 MS 的 PM & Dev 都是一起 co-work 的,只是 PM 面對客戶的時間比較多,主要負責寫 spec(相當於台灣的 PA/SA 的工作),但是過程中要密切跟 Dev (lead) 討論系統設計(SD)的問題,最後由 Dev 負責把程式實作出來(PA 大概算基本能力吧)。

另一個很明顯的重點是 Tester (QA) 是很重要的職位,必須要請人專職負責,而不是把 testing 當做 Dev 的工作中的其中一項。從這裡也可以思考,如果像微軟這樣重視 testing 的公司做出來的產品還是有可能被批的滿頭包,那麼沒有專業請人做 testing 的公司做出來的產品,品質/安全性會是怎麼樣?

扯遠了,Bentham 說,在 MS 內你可以自由選擇要做上述三種工作的哪一種,並且每種職位還可以進一步選擇要做 Indivisual Contributor (IC) 或是 Lead (manager)。

MS 的 Dev 都是很聰明而且非常有自主性的,基本上可以說整間公司都是自我實現的熱血的人(自我實現這個 term 請參考 Maslow’s hierarchy of needs),所以不適合用「公司政策」這種政治性的手段來強迫推行什麼制度(e.x., unit testing),因此 MS 管理 Dev 的原則是先盡可能提供他們一個舒適的工作環境(食物啦、飲料啦),之後要推動政策的時候,只要能夠說出個道理(e.g., unit testing 的好處),就能讓 Dev 自動自發的去執行了。

MS 的 Dev 有什麼需求呢:
  1. (Free) Food:Google 也是這樣搞的。台灣微軟好像也差不多。MIC 和 MIT 都有很多零食飲料。
  2. Quite (environment):就是說喔,不要跟 sales 坐同一間辦公室啦!
  3. Keyboard:在 199x 年的時候 MS 很多 top Devs 比較習慣 unix-like 的 text editor/command-prompt tool,很不喜歡用滑鼠的
  4. Cool idea:設法把公司要推動的東西塑造成很酷的,讓 Dev 認為做這些事情是他們自己想要的
  5. Ship it:「我的程式被幾千萬人使用」是 MS Devs 成就感的來源,所以儘快 ship product 是很重要的
所以要推動 unit testing,首先滿足上述前四項之後,利用第五項來設定一個門檻:unit testing 沒達到門檻就不給你 check in,就不能 ship product,這樣 Devs 就會嚇到了。

另外一個故事是以前 MS 每週會舉辦一個 tool 比賽,因為 Devs 在平常工作的時候很喜歡自己做一些小 tool 來自動化一些重複、繁瑣的工作,因此為了鼓勵這個風氣,每週舉辦一個 tool 比賽讓大家炫耀一下自己的作品,大家覺得不錯的 tool 就會考慮整合到產品中,據說 VSTS 的 testing framework 就是把這類 tool 整合進產品的結果。

呼,寫到這裡有點像流水帳,不過其中有很多可以好好思考的地方。就讓我用「這跟台灣真是差很多阿!」來草草結尾吧,千言萬語,不知從何說起阿~ :p

如何快速取出內嵌於 Microsoft Word 檔的大量圖片

上個週末老爸問我一個問題:要怎樣把 word 裡面的圖片抓下來?
 
我想這是很簡單的問題嘛,所以我就叫他在 word 裡面點選那張圖, 然後用右鍵選單的「複製」或者按「ctrl+v」來複製圖片,再貼進小畫家另存新檔。

然後我就繼續回頭做自己的事,過了幾分鐘老爸又丟了一個新的需求:我這個 word 檔裡面圖片很多耶,這樣每張圖片都要重複一次這個動作,很麻煩耶,而且我不想每張圖片都要自己重新命名啦!

……

說實話從來沒遇到過這麼實際的需求,於是我開始思考要怎樣很方便的一次取出內嵌在 word 檔的所有圖片,而且這方法必須是對一般正常人是很簡單的,我總不能叫老爸打開 VBE 寫一段 VBA recursive 的把所有圖檔取出來,然後 call FileSystem API 去存檔吧?!

這時候我想起來去年有一次研討會講如何客製化 Office 2007 的 Ribbon,好像可以用來解決這個問題!

2009 年 5 月的 Microsoft TechNet Magazine 有一篇「A Guide to Customizing the Office 2007 Ribbon」,很適合拿來當做 reference,對 dev 來說可以當做 Office 2007 的檔案格式的入門文章。對於要做 Office Automation 的人來說也很實用,如果要深入底層追問題的話。

關鍵在於 Office 2007 的檔案格式:Office Open XML(MSDNWiki),這是一個 zip 格式,可以想像成一份 Office 2007 Document 就跟一份 HTML Document 一樣,是由文字、圖片、影片等等的資料兜出來的,這些資料都是各自獨立的檔案,最後透過 Office 把這些檔案合併為 .docx/.xslx/.pptx 等格式的單一檔案。Office 2007 Document 也是用 Markup Language 來描述的,並不是 binary 編碼的格式。

(所以在 Office System 裡面應當也有類似 Web Browser 的 Layout Engine 之類的東西)

那麼到底要如何一次取出 word 檔內的所有圖片呢?請按照以下操作步驟:
  1. 若是由 Word 2003 建立的 .doc 檔,請先用 Word 2007 打開。(若是 .docx 格式請直接跳到步驟 3)
  2. 將 .doc 檔案另存為 .docx 格式。(這時可能會跳出一些警告訊息說格式可能會跑掉,請直接忽略它,圖片並不會因此被扭曲變形)
  3. 將附檔名從 .docx 改為 .zip。
  4. 解壓縮這個 zip 檔,word 檔中所有的圖片會位於 word\media 資料夾中。
就是這麼簡單,雖然這種需求可以說十年才遇到一次,但是要是不知道這種接近 hack 的技巧,處理起來還真是很頭大呢!(我猜可能網路上可以找到現成的小工具來做這件事,但是我懶惰沒有去找 XD 如果這個小工具還要安裝的話,感覺也不太保險…)

PS. A Guide to Customizing the Office 2007 Ribbon 中有提到:
After you've edited the contents of the package, you need to change the file extension back from .zip to its original extension. But you don't have to keep changing the extension to .zip each time you want to edit the underlying package. Instead, you can use a utility that will recognize your Office Open XML Format document as a ZIP package without ever changing the extension in the first place. There are at least a few of these. One open source option that I like is 7-zip. After you install it, just right-click your Office Open XML Format document, point to 7-zip, and then click Open Archive. You can even edit XML document parts directly in the package, and the archive utility will prompt you to update the package after you save your changes.


我只能說 7-zip 真是太優秀啦!又免費阿!有裝 7-zip 的話就不用把副檔名改成 zip 了,直接就可以把 .docx/.xslx/.pptx 內的檔案解壓縮出來到你指定的資料夾囉!

另外,A Guide to Customizing the Office 2007 Ribbon 裡面的 xml sample code 是有問題的,不能用「<Ribbon></Ribbon>」,要全部用小寫:「<ribbon></ribbon>」

2009年4月4日

網頁視窗全螢幕化

之前坎尼也有遇過這個問題
客戶希望我們的地圖畫面能大一點
還能兼顧查詢出來的結果顯示
所以最後用了程式控制 browser 全螢幕

這個方法要運用的就是 dom 裡的 window.open
window.open(url, name, specs, replace)

對,重點就是 specs 裡所填的參數
一般來講,可以用 left & top 屬性來控制開啟視窗的初始位置
height & width 控制長寬
menubar、toolbar、statusbar 來控制 browser 上一些哩哩扣扣東西的開啟
全螢幕則是利用 fullscreen=yes

在程式裡的寫法則是如下

點下 OpenWinFullScreen 之後,即會開啟全螢幕的新視窗
下圖由於要表現全螢幕,所以就抓了整個視窗的畫面 XD
可以看到,ToolBar、MenuBar、Status通通不見了
(當然也沒有關閉鍵,想關視窗請用 Alt+F4 )


另外剛剛坎尼在測試 window.open 方法時,又發現了一些有趣的東西
window.open要傳入的第二個參數 name,表示要開啟視窗名稱
若是輸入 _self 則是會在自身的視窗上作開啟

坎尼異想天開的把 name 指定為 _self 且 fullscreen=yes
你猜怎麼著??? 全螢幕的屬性就失效啦 :P

經測試,Specs裡所填的屬性在 name=_self 的情況下,通通沒效用
所以坎尼大膽推測 window.open(URL,"_self") == location.href=URL

其實還有測出蠻多有趣的東西
但目前坎尼用的環境是 win7 + IE8
所以很多還待驗證 (想用 winxp 或 win2k3 + IE 6 7 8 測)
這些留待未來再來驗證吧 XD

剛剛發現 windows 7 裡有個 snipping tool
可以用來框選畫面抓圖,算是還不錯用
(記得大學時都是print screen小畫家去修圖)

Google Spreadsheet 裡用規則運算式

最近因為工作關係,遇到要用 Google Form 及 Google Sheet 所以研究了 Google Sheet 裡的一些 function 怎麼用 首先,分享一下如何在 Google Sheet 裡用規則運算 :D