2008年8月30日 星期六

一個好的開發人員帶你上天堂,數個鳥開發人員拖你下地獄



  最近上網查資料,意外在我訂閱的部落格中,一個深入探討許多 .net 技術的優良部落格黑暗執行緒中挖到一篇好文,探討現今專業不被重視的社會中,優秀的工程師和平庸的工程師之間的天壤之別。像是這麼偏僻入裡的文章,身為技術人員而為榮的我一定要大推一下的啦:


  Developers, Are You Underpaid Or Overpaid? ( 雖然英文標題,但是中文文章 )


  其中有一段作者描述和新來的工程師相處的際遇,更是看得我在四下無人下頻頻點頭:


  「想起在前公司有個開發人員,我將一個案子交給這位前同事接手,幾天過去了,沒有聽到任何消息,心想:很好,事情應該很順利!又幾天過去了,我晃到他座位旁去關心一下進度,他老兄居然跟我說,他搞不太懂其中幾項需求,原來這陣子的時間全都在『搞懂需求』這件事上空轉。」


  這讓我想起最近帶著新同事合作開發專案的狀況。


  記得兩年前我跟著師父投奔去新竹時,也發現那邊半導體封測廠的老闆對軟體專業的不重視。既然花了大錢和公司股票請獵人頭公司挖角師父,卻在軟體開發專業上又不採納其意見,一昧地在言談表達覺得寫程式沒甚麼大不了。因為彼此對對方的專長領域不熟悉,每次爭論總淪為角力,看誰能把話題轉到自己的領域上就可讓對方辯無可辯,最後討論總變為模糊焦點的爭論...。


  但是想當然爾,CEO 和 RD 頭之間的戰爭誰比較可能獲得最後勝利?當然最後人事違和之下結束了我短命的新竹之旅,雖然這一出走也同時引爆該公司大量的開發人員陸續出走...。


  總之,這篇讓我心有戚戚焉的文章,希望廣為留傳,讓更多人知道工程師之間的差異決不是表面上看來這個簡單的計算!


  裡面有句重點:「優秀的開發人員通常薪水是偏低的,而鳥鳥的開發人員則多領了不該領的錢。


  最懂得精打細算的老闆們,到底應該好好善待幾個物超所值的優秀開發人員?還是大不了多顧幾個鳥鳥的開發人員來頂替他?


2008年8月24日 星期日

因為蝴蝶效應,所以軟體專案管理與眾不同。


  為何拿到了當紅專案管理師證照 ( PMP ) 的專業 PM,遇到軟體專案的管理實務仍是經常吃鱉和踢到鐵板?專案管理的需求普遍出現在各行各業,但為何唯獨軟體專案的管理可以不斷地在書店中推陳出新一再討論?到底,軟體專案的與眾不同之處在哪裡?為何軟體的品質如此難以掌握?
  說穿了,軟體專案的機動性、變動性與不確定性是遠高出其他性質的專案,而且,軟體的變動是最容易產生所謂「蝴蝶效應」。
  「巴西的蝴蝶煽動翅膀,引發德克薩州的暴風雨」誠可描述軟體專案常引發的系統現象。
  過去經驗已經證實,一般工程界常使用的瀑布式開發在軟體專案已證實並不適用,原因一方面是發生需求的機動性、另外是專案生命週期短暫,資源與時間成本不足以在開發前釐清所有需求與定案。

  但上面所述是後天人為環境所造成的特性,我們探討一下軟體開發本身的特異性,就是考量日後維護方便,而在軟體工程上不斷強調的共通性的抽離。常看軟體架構的書,一定會時常看到下圖這種類似堆積木的圖表 ( From Google Andriod architecture overview ),這代表的就是軟體環境是仰賴著基礎建設進行疊床架屋的模式演繹:

  想想看,高樓大廈蓋了差不多的時候,才發現當初地基打得不夠深,有可能不拆掉房子回頭把地基挖深嗎?但是在軟體專案中,釜底抽薪卻是十分常見的招數。程式跑得不夠穩?直接升級作業系統吧 ( 98 --> XP ),程式跑得不夠快?降級作業系統吧 (Vista --> XP )。
  綜觀其他業界,對於個別專案其實都有「資源獨佔」的特色,而「整合、開放、互通」卻是資訊軟體業的特色,也正是蝴蝶效應的溫床。想想看,一個建設公司為了降低成本或是強化材質而採用了新的混凝土水泥配方,會影響到該公司之前已經完工的大樓嗎?已經完成的部分幾乎已成定局,幾乎不會受其他外界因素改變而影響,這就是我所謂的「資源獨佔性」,但資訊業的整合技術的通透性,卻非如此。已經完工的功能模組、甚至已經上線運行多年的系統,因為外界一個看似毫不相關的改變而受衝擊的例子我隨便回想也有十多種案例。
  隨手舉個真實案例,來說明這種意料外的蝴蝶效應。
  某企業外包其薪資系統,該薪資系統是根據該企業現存共通的 HR ( 人力資源 ) 資料庫進行規劃與設計。得標的資訊公司因受限該企業現存的 HR 資料庫的結構與欄位限制,所以某部分報表所需使用到的暫存計算結果都是必須即時運算得出,而使上線幾個月的薪資系統導致「可正常使用但是效能不彰」的批評。
  於是該專案的 PM,經過評估,做了個「非常小的變動,但可大幅提升效能」的決定:就是要求在該 HR 的員工資料表 (Employee table ) 中添加一個新欄位 ( 假設新欄位名為 RowCount ),用來做為記錄最後一次計算結果,該欄位的資料只在相關資料變動時做必要的更新,如此以往每次跑報表需要即時計算加總的資料,變成立即可以隨手取用,效能表現的確讓在場所有人笑顏逐開。
  這個決定的風險考量呢?大家直覺的反應:「資料庫現存的欄位與資料全部沒有任何改變和影響,對現有的舊程式不會有任何衝擊。」是啊,一個 DLL library 原本有 10 個 API,多一個新的變成 11 個 API,對已經在使用原本就有的 10 個 API 的程式來說應該沒有影響啊。
  是嗎?也許有經驗的開發人員已經嗅出這個決定所忽略的風險是什麼了,但故事先繼續下去。
  新版的薪資系統幾經測試看來一切順利,翻翻黃曆挑了個黃道吉日上線,卻發現早已運行多年的 HR 人資系統突然間當機連連無法使用!人資系統的原始廠商在未事前照會、且系統已經使用多年乏人問津,是否仍在保固或是否有能力進行保固皆在未定之天的情況下,給了個想當然爾的回覆:「多年使用都沒出過事 ( or 其他那麼多客戶都沒出事 ),一定是你們自己做了什麼不可告人的勾當!」
  結局當然,新版的薪資系統被迫退版下線。其實造成 HR 系統無法運作的原因很簡單,因為 HR 系統內有個 SQL 語法把員工資料表與薪資記錄表連接起來:
SELECT * FROM Employee, Salaries WHERE Employee.ID = Salaries.EmployeeID
  而恰恰好,這個薪資記錄表內正好有個和 Employee 新添加的欄位同名同姓的 RowCount 欄位,這使得原本 HR 系統可以單純以 RowCount 找到他所需要的資料,卻變成必須透過前置詞 Salaries.RowCount 才能抓到正確的資料。
  這個問題好解決,新版的薪資系統改用其他不會產生重複衝突的欄位名稱即可。
  也許看這篇文章的人早料到這樣的風險並內心暗自批評該團隊太不專業,這麼顯而易見的風險都沒評估到。但我想重點是:不經一事不長一智各位自認專業有經驗的傑出人員在進行任何改變的決策之前,又真的有自信能評估到所有不可見的風險嗎?自認為的小改變、小需求,真的只是小改變、小需求嗎?還是你只看到冰山那一角
  如果經驗和遠見,真的只能從錯誤中學習 ( 我同意的確只能如此 ),在長江後浪推前浪之下,那誰來替我們客戶所使用的軟體做品質把關?前幾個客戶就當真是倒楣的白老鼠,給實習醫生練開刀的?
  在不預設立場的情況下,不論是十多年經驗的 PM 或是初掌兵符的 PM,軟體的品質唯有「測試、測試、再測試」,一句話,真金不怕火煉而已
  但是,完整的高密度測試,從單元測試、系統整合測試、壓力測試,所耗費的代價與人力大不大?非常巨大!
  若有認為測試沒啥大不了的想法,就代表根本沒在好好用心測。正常說來,測試和開發的成本比差不多 1 : 1 ( 但實務上客戶總會壓縮測試時程,這就是外行領導內行 )。
  回顧到此的重點:軟體專案的測試成本之高,源自於資訊環境容易產生「蝴蝶效應」所致,所以任何改變所引發的測試,決不只是表面上所看到的那些改變的測試,而是一個「全面性的測試」。
  將測試粗分為三個大階段,即是大家所熟知的 Alpha 、 Beta 、 Release Candidate ( RC ) ,之後 RTM ( Ready To Manufacture ) 幾本上就是進工廠量產的原型母片,不列入其內。
  各個軟體公司可能對這三大階段的定義略有不同,但大致上如下:

  • ALPHA:所有需求已凍結與定案,這階段的測是全力在找出所有程式錯誤臭蟲並修補。然而,在這個階段還可以做的重大決定,就是「拿掉」某些功能。然而這個拿掉的動作,不是單純的拿掉,是具有技巧性的以減低影響和風險,這部分稍後詳細介紹。


  • BETA:連「拿掉」的動作皆不再允許,功能規格 100% 確立,此階段全力檢驗前一階段找出的所有錯誤與臭蟲是否掃除乾淨,並將所有步驟重新來過,以便偵測出修補的動作是否引發新的錯誤臭蟲。


  • RC:已知的臭蟲已減少到可接受的範圍,開始進行使用者接受度測試,有些軟體公司會下放給外界第一階段的使用者或是特定社群做測試,以便回報更多可用資訊,或是在公司內部開始強制規定自己的一般員工開始安裝並使用此軟體以求意見回饋。這個階段的收穫基本上不改變產品架構與行為,多半影響使用說明文件的製作方式或是包裝行銷的模式。


  上面這三大階段可在各自細分,但我就不多說了。
  現在回頭細談在 ALPHA 階段移除功能這件事情。移除功能,是減少測試的負荷並追趕上市時程的常見手段,通常是發現某功能的相關錯誤怎麼測也測不完、修也修不完,這時只能忍痛拿掉。所以我們常見到世界某大軟體公司的產品,在 ALPHA 階段內建或是宣稱的功能,在 BETA 階段斷然消失,每次釋出的測試版本也都會有行小字提示:現在看到的不見得是真的,一切以上市後的正式產品為準。
  在上篇「專案經理到底該怎麼做」的文章,我強烈表示在 ALPHA 階段末期加入新需求是不智之舉,其中一個原因,就是專案經理預期不到的「蝴蝶效應」會讓整個專案進度倒退到 ALPHA 階段前,所有的測試必須重新來過,這等同於之前在 ALPHA 階段的測試投資全都是白費,延誤專案的可能性風險大增!
  那麼,拿掉功能不也有同樣的風險嗎?是的,所以說拿掉是有技巧的,拿掉不見得是移除,並不需要把相關的程式碼找出然後按下鍵盤的 [ DEL ]  鍵或是 [ Backspace ] 來刪光光,而是只要封蓋,讓使用者看不到摸不著即可。使用者無法使用該功能,不代表你系統的其他模組沒有呼叫該相關的程式碼,所以必須不見光地保留,讓風險降到最低。
  很多臭蟲大多是異常輸入或是異常處理沒有做好,封蓋的第一個好處就是免除了該功能對 Monkey Test 的反應與測試,但不影響其他程式碼的穩定性。
  所以我們會聽說一些世界某大軟體公司的產品有些非文件記載的 API 流出 ( 即代表對此 API 的功用不保證,如果你開發的軟體硬要使用,後果自負 ),或是遊戲軟體有密技可以出書,或是某些軟體有後門或隱藏功能可以使用... etc。
  就算使用「封蓋」的方式拿掉某些功能,全面性的重新測試仍是必須的,但是因為直接接觸使用者的面積減少,所以也同時減少了接下來三個階段的 Test scenario,因此對整個專案的時程影響不會太巨大。
  談完以上這些,我必須說軟體專案有其特異性,沒有實務上累積開發技術經驗的人,就算拿了 PMP 並且整天抱著個 PMBOK 在說嘴的人,根本不可能管理好軟體專案,也不可能是值得與他討論的對象。

Google+ Badge